1647 - 搬寝室
时间限制 : 1 秒
内存限制 : 32 MB
搬寝室是很累的,xhd深有体会.时间追述2006年7月9号,那天xhd迫于无奈要从27号楼搬到3号楼,因为10号要封楼了.看着寝室里的n件物品,xhd开始发呆,因为n是一个小于2000的整数,实在是太多了,于是xhd决定随便搬2*k件过去就行了.但还是会很累,因为2*k也不小是一个不大于n的整数.幸运的是xhd根据多年的搬东西的经验发现每搬一次的疲劳度是和左右手的物品的重量差的平方成正比(这里补充一句,xhd每次搬两件东西,左手一件右手一件).例如xhd左手拿重量为3的物品,右手拿重量为6的物品,则他搬完这次的疲劳度为(6-3)^2 = 9.现在可怜的xhd希望知道搬完这2*k件物品后的最佳状态是怎样的(也就是最低的疲劳度),请告诉他吧。
题目输入
每组输入数据有两行,第一行有两个数n,k(2<=2*k<=n<2000).第二行有n个整数分别表示n件物品的重量(重量是一个小于2^15的正整数).
题目输出
对应每组输入数据,输出数据只有一个表示他的最少的疲劳度,每个一行.
输入/输出样例
输入格式
5 1 18467 6334 26500 19169 15724 7 1 29358 26962 24464 5705 28145 23281 16827 0 0
输出格式
492804 1399489
C语言解答
#include <stdio.h> #include <stdlib.h> #define maxn 2010 #define INF 1000000000 #define min(A,B) ((A)<(B))?(A):(B) int A[maxn], dp[2][maxn]; int cmp(const void * a, const void * b) { return ( *(int*)a-*(int*)b); } int main() { int n, k; while(scanf("%d%d",&n,&k) != EOF) { if(n==0&&k==0) break; for(int i = 1;i <= n; i++)scanf("%d",&A[i]); for(int i = 0;i <= 1; i++){ for(int j = 0;j <= n; j++){ dp[i][j]=INF; } } for(int i = 0;i < 2; i++)dp[i][0]=0; qsort(A+1,n,sizeof(int),cmp); for(int i = 2;i <= n; i++) { for(int j = k;j >= 1; j--){ int temp = dp[1][j]; dp[1][j]=min(dp[0][j-1]+(A[i-1]-A[i])*(A[i-1]-A[i]),dp[1][j]); dp[0][j]=temp; } } printf("%d\n",dp[1][k]); } return 0; }
C++解答
#include <stdio.h> int n,k,b[2222][1111]; int run() { int i,j,a[2222],s,l; for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) if(a[i]>a[j]) { l=a[i]; a[i]=a[j]; a[j]=l; } for(i=0;i<=n;i++) for(j=0;j<=k;j++) b[i][j]=-1; b[0][0]=0; for(i=0;i<=n;i++) for(j=0;j<=k;j++) if(b[i][j]!=-1) { s=b[i][j]+(a[i+1]-a[i+2])*(a[i+1]-a[i+2]); if((b[i+2][j+1]==-1)||(b[i+2][j+1]>s)) b[i+2][j+1]=s; if((b[i+1][j]==-1)||(b[i+1][j]>b[i][j])) b[i+1][j]=b[i][j]; } printf("%d\n",b[n][k]); } int main() { scanf("%d%d",&n,&k); while(n!=0) { run(); n=0; scanf("%d%d",&n,&k); } return 0; }