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 }