hdu-1421搬寝室(dp)
http://acm.hdu.edu.cn/showproblem.php?pid=1421;
思路:先将所给的椅子的价值按升序排列,举个例子,四张椅子的价值分别为a,b,c,d(a<b<c<d);
那么分别两两组合(ab)(cd);
(ac)(bd);(ad)(bc);
三种价值分别为(a-b)2+(c-d)2,(a-c)2+(b-d)2,(a-d)2+(b-c)2;
那么要比较它们的大小只要比较非平方项的大小就可以了。
(ab+cd),(ac+bd),(ad+bc);
两两项相减比较的第一项最大,那么也就是负的最大,那么第一个式子的值是最小的。
所以要搬椅子肯定要搬相邻的两项。
动态转移方程---
if(j==2*i)
{
dp[i][j]=dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]);
}
else
{
dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]));
}
dp[i][j]表示当选i组时第j个数选不选的的最小值,如果正好达到第2*i个数dp[i][j]=dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]),就必须要先初始化,使之包含有2*i个数,
然后dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]))表示第j个数选不选,如果不选就是dp[i][j-1],如果选就要连着前一个数一起选,
那么就是dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]);
最后结果是dp[p][q];
1 #include<stdio.h> 2 #include<algorithm> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<iostream> 6 #include<queue> 7 const long long N=1e16; 8 using namespace std; 9 long long a[3000]; 10 long long dp[3000][3000]; 11 int main(void) 12 { 13 int i,j,k,p,q; 14 while(scanf("%d %d",&p,&q)!=EOF) 15 { 16 for(i=1; i<=p; i++) 17 { 18 scanf("%lld",&a[i]); 19 } 20 sort(a+1,a+1+p); 21 for(i=0; i<=p; i++) 22 { 23 dp[0][i]=0; 24 }//初始化 25 for(i=1; i<=q; i++) 26 { 27 for(j=2*i; j<=p; j++) 28 { 29 if(j==2*i) 30 { 31 dp[i][j]=dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]); 32 } 33 else 34 { 35 dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1])); 36 } 37 } 38 } 39 printf("%lld\n",dp[q][p]); 40 } 41 return 0; 42 }