将n件物品排序,每次拿的必定是相邻的两个。先做预处理另s[i]为搬动第i和i-1件物品的疲劳度,另f[i][j]表示从前i件物品中搬动2*j个物品的疲劳度最小值。状态转移方程为:f[i][j]=min(f[i-1][j],f[i-2][j-1]+s[i]);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXM 0x7FFFFFFF
using namespace std;
const int N=2015;
__int64 a[N],s[N],f[N][N]={0};
__int64 min(__int64 x,__int64 y)
{
return x<y?x:y;
}
void work(int n,int k)
{
int i,j;
for(i=1;i<=n;i++) scanf("%I64d",&a[i]);
sort(a+1,a+n+1);
for(i=2;i<=n;i++) s[i]=(a[i]-a[i-1])*(a[i]-a[i-1]);
for(i=1;i<=n;i++)
for(j=1;j<=k;j++)
f[i][j]=MAXM;
for(i=2;i<=n;i++)
for(j=1;j<=i/2;j++)
f[i][j]=min(f[i-1][j],f[i-2][j-1]+s[i]);
printf("%I64d\n",f[n][k]);
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
work(n,k);
return 0;
}