#include<stdio.h>
#include<stdlib.h>
#define N 2100
int n,k,Weight[N],result_map[N][N/2] = {0};
int cmp(const void *a,const void *b)
{
return *(int*) a-*(int*) b;
}
void result()
{
for(int i = 2;i<=n;i++)
for(int j = 1;j<= i/2;j++)
{
int temp1,temp2 = 0;
temp1 = result_map[i-1][j];
temp2 = result_map[i-2][j-1] + (Weight[i]-Weight[i-1])*(Weight[i]-Weight[i-1]);
if(j*2 == i)
result_map[i][j] = temp2;
else
result_map[i][j] = (temp1>temp2)?temp2:temp1;
}
}
void output()
{
printf("%d\n",result_map[n][k]);
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
Weight[0] = -1000;
for(int i = 1;i<=n;i++)
{
scanf("%d",&Weight[i]);
}
qsort(Weight,n+1,sizeof(int),cmp);
result();
output();
}
return 0;
}
最坑的是这题尼玛尽然能输入多组数据。。。让我WA了n次。。。顿时哭了
这题不简单。要做出来,首先要认识到这样一个数学规律:
证明:从4个数中 a b c d
选取相邻的两个数一定是最小得
及:(a-b)^2+(c-d)^2 < (a-c)^2+(b-d)^2 < (a-b)^2+(c-d)^2 < (a-d)^2+(b-c)^2;
先排序,假设从n-1个中选取k对是最少得,那么从n个中选取k对,可以这样分析 对n-1个数 再在末尾增加一个数,那么这个数可能被选中成为k对中其中一对,可能不被选中,如果不被选中,那么从n个中选取k对就相当于从n-1个中选取k对,如果被选中,之前证明了选中的数必须是连续的两个才能事最小,那就相当于从n-2个数中选取k-1对加最后两个数成为,这样,
状态转移方程就为dp[i][j] = min { dp[i-1][j] , dp[i-2][j-1] + (a[i-1]-a[i])*(a[i-1]-a[i]) };
但如果j*2 == i 成立,则dp[i][j] = dp[i-2][j-1] + (a[i-1]-a[i])*(a[i-1]-a[i]) 。
(注意一定不要用除法判断即j == i/2。整数除法会让你变得很郁闷 = =)