动态规划之 <筷子>
2013-11-14 21:07
169 查看
描述
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;
}
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;
}
相关文章推荐
- 动态规划之 <筷子>
- <table>标签 利用DOM 的方法和属性实现对表格的动态操作
- 动态规划---->每对定点之间的最短路径 Floyd(弗洛伊德)算法
- 工信部<<大数据产业发展规划>>
- <iOS>动态改变导航栏颜色
- 动态规划---->每对定点之间的最短路径 Floyd(弗洛伊德)算法
- 动态规划---->货郎担问题
- 工信部<<大数据产业发展规划>>
- <android> SCREEN_ON SCREEN_OFF黑屏, 亮屏消息只能动态注册
- 解决用<img src="<%# Eval("ShowPhoto")%>"动态绑定图片,发布到IIS上无法显示的问题
- 动态规划---->货郎担问题
- 动态规划---->可靠性设计
- 动态规划 筷子(STICK)
- 动态规划---->0/1背包问题
- <mvc:default-servlet-handler />不能同时访问静态资源和动态资源的问题
- <JAVA与模式>之动态代理
- 一本通上的某动态规划题:股票买卖(openjudge->NOI->2.6->8464)
- 总结: 0-1背包问题 --> 动态规划d…
- 动态引入“”和<>文件
- <video>标签:视频播放器动态设置src