Chopsticks
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=234
题目大意:给定n个筷子的长度,取k+8套筷子,每套有3个,长度分别为A,B,C。要求k+8套筷子中(A-B)^2的和最小,输出这个最小值。
分析:题目中筷子长度是非降序排列的,所以最小的两个A和B一定是相邻的。先不考虑筷子C,只要留着就行。
令dp[i][j]表示从 j 个筷子中取 i 套筷子的最优值。
dp[i][j] = min {dp[i][j-1] , dp[i-1][j-1] | (n - j > 3*(k - i))剩下的筷子可以凑满}
可以用滚动数组
代码如下:
1 # include<iostream> 2 # include<cstring> 3 # include<cstdio> 4 using namespace std; 5 long MAX = 2147483647; 6 long dp[1005][5005]; 7 long f[5005]; 8 int main(){ 9 int T,i,j,k,n; 10 long temp; 11 cin>>T; 12 while(T--) 13 { 14 scanf("%d%d",&k,&n); 15 for(i=1;i<=n;i++) 16 cin>>f[i]; 17 k += 8; 18 memset(dp,0,sizeof(dp)); 19 for(i=1;i<=k;i++) 20 { 21 for(j=i*2;j<=n;j++) 22 { 23 dp[i][j] = MAX; 24 if(j>i*2) 25 dp[i][j] = dp[i][j-1]; 26 if(n-j>(k-i)*3) 27 { 28 temp = dp[i-1][j-2] + (f[j]-f[j-1])*(f[j]-f[j-1]); 29 if(temp<dp[i][j]) 30 dp[i][j] = temp; 31 } 32 } 33 } 34 cout<<dp[k][n]<<endl; 35 } 36 return 0; 37 }