【dp】HDU 1421 搬寝室

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 }
dp

 

posted @ 2017-08-09 12:43  shulin15  阅读(181)  评论(0编辑  收藏  举报