您的位置:首页 > 其它

动态规划之 <筷子>

2013-11-14 09:28 495 查看
描述

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

【思路】

首先应该想到是dp问题。先sort这样第i和第i-1根就是差距最小的了,

f[i][j]表示前i根组成j双筷子每双长度差的和的最小值。

在考虑第i根筷子时,需要做出的决策即使要不要把这只筷子加入到最优解中去,

若加入,则其与第(i-1)根筷子组成一对,f[i][j]=f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]),否则f[i][j]=f[i-1][j] .

当然,上述决策过程依赖于以下先验知识:

当从小到大排好的 a,b,c,d 四根筷子组成两双时, ab,cd 这样的组合最优. 就是以上决策时采取的 将第i个筷子跟第i-1根组成一对.

故dp方程这样写

f[i][j]=min(f[i-1][j],f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]));

【代码】

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<climits>

#include<cstring>

#include<algorithm>

using namespace std;

int f[200][200],a[200];

int n,k,i,j;

int min(int a,int b)

{

if(a<b)

return a;

else

return b;

}

void init()

{

scanf("%d%d",&n,&k);

if((k+3)*2>n)cout<<-1<<endl,exit(0);

for(i=1;i<=n;i++)

scanf("%d",&a[i]);

sort(&a[1],&a
+1);

}

int main()

{

init();

memset(f,0x3f,sizeof(f));

for(i=0;i<=n;i++)f[i][0]=0;

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]+(a[i]-a[i-1])*(a[i]-a[i-1]));



printf("%d\n",f
[k+3]);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: