搬寝室
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 63 Accepted Submission(s) : 30
2 1 1 3
4
//可以证明出来对于不减序列,得到最小疲劳度应该选择2个相邻的数字,而不是交叉的数字
//dp[i][j]表示在前j件物品中选择i对物品的最小疲劳度(j>=i*2)
// 则可以分为j与j-1是一对(j=i*2),j与j-1不是一对(j>i*2)
//j与j-1是一对时,应在前j-2件物品中选择i-1对,再加上j与j-1的疲劳度
//即dp[i][j]=dp[i-1][j-2]+(list[j]-list[j-1])^2
//j与j-1不是一对时,说明第j个物品没有被选到,应该在前j-1件物品中选择i对
//即dp[i][j]=dp[i][j-1]
//综上dp[i][j]=min(dp[i-1][j-2]+(list[j]-list[j-1])^2,dp[i][j-1])
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int list[2200];
int dp[1100][2200];
int min(int a,int b){
return a<b?a:b;
}
int main(){
freopen("in.txt","r",stdin);
int n,k;
while(scanf("%d%d",&n,&k)!=EOF){
memset(list,0,sizeof(list));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
scanf("%d",&list[i]);
}
//物品重量应为不减序列
sort(list+1,list+n+1);
for(int i=1;i<=k;i++){
for(int j=2;j<=n;j++){
if(j==i*2){
//j与j-1配对
dp[i][j]=dp[i-1][j-2]+(list[j]-list[j-1])*(list[j]-list[j-1]);
}else{
//j与j-1不配对
dp[i][j]=min(dp[i-1][j-2]+(list[j]-list[j-1])*(list[j]-list[j-1]),dp[i][j-1]);
}
}
}
printf("%d\n",dp[k][n]);
}
return 0;
}