大理石分割(动态规划)

大理石分割(动态规划)

有若干块大理石,其大小及美观程度不一,为了比较客观的分割这些大理石,我们需要先给这些大理石一个评分,评分分为6个等级,分别用1~6的数字来表示。现希望将这些大理石分成两部分,使每部分的评分之和相同。
输入:
输入一行,包括6个数,分别是每个等级的大理石的数量。每种等级的大理石数量不超过20000.
输出:
如果这些大理石能否分割成评价等级之和相同的两部分,则输出true,否则输出false.
样例输入:
1 0 1 2 0 0
样例输出:
false

算法分析

试想如果可以分配,那么是否可以找到一种分配方案使得使用得大理石数量最少。如此,该问题,就变成了货币兑付问题。
就该问题,以score【6】来保存各等级大理石得输卵不过,均值avg=sum/2=6;所以后面以用6种面值得货币(大理石)来兑付avg价值的货币来进行描述:
在这里插入图片描述动态规划表如下表所示:
qi在这里插入图片描述
其中最左列表示0-6种纸币,其价值分别为0-6,行为0-avg的价值的纸币需要兑付的,因为其中avg为6.
首先初始第2列为0,第一行为∞。数量不够即表示该价值的纸币不能被兑付以无穷表示。
现在开始填第3行,首先填第3行3列即v【1,1】,用前1种纸币来兑付价值为1的纸币,第一种其数量可选为0-1,当为0时,使用的数量为0+V【0,1-01】=∞,当为1时,使用的数量为1+V【0,1-11】=1。故V【1,1】=1,同理v[1,2]时,第1种货币的数量仍为0-1,当为0时,使用的数量为0+V【0,2-01】=∞,当为1时数量为1+V【0,2-11】=∞,所以V【1,2】=∞。同理填完第3行。
接下来填第4行,首先填4行3列,V【2,1】,用前2种货币来兑付价值为1的纸币,第2种货币其数量可选为0,故V【2,1】=0+V【1,1-0*2】=1,同理V【2,2】=∞,以此填完所有的。

最后,由于我们的目的是为了兑付价值为6的纸币可是V【i,6】始终为∞,所以不可兑付。即不可均等分割。同理当V【i,6】不是∞时证明可分割,动态规划即可结束。
至于分配方案,读者可以自行思考一下。可以借鉴0-1背包动态规划。

代码

#include <stdio.h>
#define MAX 10000
int score[6]={0,1,2,0,0,0};
int avg;
int predict()
{
int V[7][avg+1];
/*
初始化,MAX为无穷
/
for(int i=1;i<avg+1;i++)V[1][i]=MAX;
for(int i=1;i<7;i++)V[i][1]=0;
//填表
for(int i=2;i<7;i++)
for(int j=2;j<avg+1;j++)
{
int min=MAX;
for(int k=0;k<score[i];k++)
{
if(k+V[i-1][j-i
k]<min)min=k+V[i-1][j-i*k];
}
V[i][j]=min;
}
//判断是否可分割
for(int i=2;i<7;i++)
if(V[i][avg]<MAX)
{
printf(“true”);
return 1;
}
printf(“false”);
}
int main(int argc, char argv[])
{
int sum=0;
for(int i=0;i<6;i++)
{
sum+=score[i]
(i+1);
}
if(sum%2)printf(“false”);
else{
avg=sum/2;
predict();
}
return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值