hdu1421 搬寝室 DP

转载:

/*证明:从4个数中 a b c d  依次递增;

选取相邻的两个数一定是最小得

及:(a-b)^2+(c-d)^2<(a-c)^2+(b-d)^2&&(a-b)^2+(c-d)^2<(a-d)^2+(b-c)^2;

//先排序,假设从n-1个中选取k对是最少得,那么从n个中选取k对,可以这样分析 对n-1个数 再在末尾增加一个数,那么这个数可能被选中成为k对中其中一对,可能不被选中,如果不被选中,那么从n个中选取k对就相当于从n-1个中选取k对,如果被选中,之前证明了选中的数必须是连续的两个才能事最小,那就相当于从n-2个数中选取k-1对加最后两个数成为,这样,状态转移方程就为dp[i][j]=min(dp[(i-1)][j],dp[(i-2)][j-1]+(a[i-1]-a[i])*(a[i-1]-a[i]));

*/

我的AC代码:

 1 #include<cstdlib>
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 #define MAX 2010
 9 int dp[MAX][MAX];
10 int f[MAX];
11 int n,k;
12 int main()
13 {
14        while(scanf("%d%d",&n,&k)!=EOF)
15        {
16                int i,j;
17                for( i=1;i<=n;i++)
18                        scanf("%d",&f[i]);
19                sort(f+1,f+n+1);
20                memset(dp,0,sizeof(dp));
21                for( i=2;i<=n;i++)
22                        for( j=1;j<=k&&j*2<=i;j++)
23                                if(i==j*2) dp[i][j]=dp[i-2][j-1]+(f[i]-f[i-1])*(f[i]-f[i-1]);
24                                else
25                                dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(f[i]-f[i-1])*(f[i]-f[i-1]));
26                cout<<dp[n][k]<<endl;
27        }
28        return 0;
29 }
View Code
原文地址:https://www.cnblogs.com/xiaozhuyang/p/hdu1421.html