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】

1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 9 using namespace std; 10 typedef long long ll; 11 const int maxn=2e3+3; 12 const ll inf=1000000000000000; 13 ll a[maxn]; 14 ll dp[maxn][maxn/2]; 15 int n,k; 16 int main() 17 { 18 while(~scanf("%d%d",&n,&k)) 19 { 20 for(int i=0;i<=n;i++) 21 { 22 for(int j=0;j<=k;j++) 23 { 24 dp[i][j]=inf; 25 } 26 } 27 for(int i=0;i<=n;i++) 28 { 29 dp[i][0]=0; 30 } 31 for(int i=1;i<=n;i++) 32 { 33 scanf("%lld",&a[i]); 34 } 35 sort(a+1,a+1+n); 36 for(int i=2;i<=n;i++) 37 { 38 for(int j=1;j<=k;j++) 39 { 40 ll tmp=(a[i]-a[i-1])*(a[i]-a[i-1]); 41 dp[i][j]=min(dp[i][j],dp[i-1][j]); 42 dp[i][j]=min(dp[i][j],dp[i-2][j-1]+tmp); 43 } 44 } 45 46 ll ans=inf; 47 for(int i=1;i<=n;i++) 48 { 49 ans=min(ans,dp[i][k]); 50 } 51 cout<<ans<<endl; 52 } 53 return 0; 54 }