南邮 OJ 1581 筷子

筷子

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 217            测试通过 : 36 

比赛描述

A 先生有很多双筷子。确切的说应该是很多根,因为筷子的长度不一,很难判断出哪两根是一双的。这天,A 先生家里来了K 个客人,A 先生留下他们吃晚饭。加上A 先生,A夫人和他们的孩子小A,共K+3个人。每人需要用一双筷子。A 先生只好清理了一下筷子,共N 根,长度为T1,T2,T3,……,TN。现在他想用这些筷子组合成K+3 双,使每双的筷子长度差的平方和最小。(怎么不是和最小??这要去问A 先生了,呵呵)

输入

共有两行,第一行为两个用空格隔开的整数,表示N,K(1≤N≤100,0<K<50),第二行共有N个用空格隔开的整数,为Ti每个整数为1~50之间的数。

输出

仅一行。如果凑不齐K+3双,输出-1,否则输出长度差平方和的最小值。

样例输入

10 1
1 1 2 3 3 3 4 6 10 20

样例输出

5

提示

第一双 1 1
第二双 2 3
第三双 3 3
第四双 4 6
(1-1)^2+(2-3)^2+(3-3)^2+(4-6)^2=5

题目来源





// dp[i][j]:前i只筷子组成j双 的最小平方和
// dp[i][j]=max{dp[i-1][j],dp[i-2][j-1]}
#include<stdio.h>
#include<algorithm>
int a[101];
int dp[101][54];
int main(){
//	freopen("test.txt","r",stdin);
	int N,K,i,j,temp1,temp2;
	scanf("%d%d",&N,&K);
	K += 3;
	if(N<(K<<1)){
		printf("-1\n");
		return 0;
	}
	for(i=1; i<=N; i++){
		scanf("%d",a+i);
	}
	for(i=0;i<=N;i++){
		dp[i][0] = 0;
		for(j=1;j<=K;j++){
			dp[i][j] = 10000;			//不能设为INT_MAX  WA4
		}
	}
	//dp[0][0] = 0;
	std::sort(a+1,a+1+N);
	for(j=1; j<=K; j++){
		for(i=(j<<1); i<=N; i++){
			temp1 = dp[i-1][j];
			temp2 = dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]);
			if(temp1>temp2){
				dp[i][j] = temp2;
			}else{
				dp[i][j] = temp1;
			}
		}
	}
	printf("%d\n",dp[N][K]);
}


你可能感兴趣的:(ACM,筷子,南邮OJ)