http://acm.hdu.edu.cn/showproblem.php?pid=1421
【题意】
- 给定n个数,要从n个数中选择k个二元组{x,y},最小化sum{(x-y)^2}
- 2<=2*k<=n<2000
【思路】
- 首先排序,一定选择相邻的两项作为一对
- dp[i][j]表示选择到ai,组成j对时的最小值
- 两种选择:第j对中有ai,dp[i][j]由dp[i-2][j-1]转移来
- 第j对中没有ai,dp[i][j]由dp[i-1][j]转移来
- 注意初始化
【AC】
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue> using namespace std;
typedef long long ll;
const int maxn=2e3+;
const ll inf=;
ll a[maxn];
ll dp[maxn][maxn/];
int n,k;
int main()
{
while(~scanf("%d%d",&n,&k))
{
for(int i=;i<=n;i++)
{
for(int j=;j<=k;j++)
{
dp[i][j]=inf;
}
}
for(int i=;i<=n;i++)
{
dp[i][]=;
}
for(int i=;i<=n;i++)
{
scanf("%lld",&a[i]);
}
sort(a+,a++n);
for(int i=;i<=n;i++)
{
for(int j=;j<=k;j++)
{
ll tmp=(a[i]-a[i-])*(a[i]-a[i-]);
dp[i][j]=min(dp[i][j],dp[i-][j]);
dp[i][j]=min(dp[i][j],dp[i-][j-]+tmp);
}
} ll ans=inf;
for(int i=;i<=n;i++)
{
ans=min(ans,dp[i][k]);
}
cout<<ans<<endl;
}
return ;
}
dp