动态规划之石子合并

石子游戏有两种:一种是博弈方面;另一种是合并规划方面的。前者需要太厉害的判断,而且要用到很多数学方面的结论,所以俺不会。这里主要探讨一下石子归并方面的问题与算法。

. 简单的石子合并

问题类似于背包问题:给出n堆石子的数量,请你求出:由这n堆石子可以合并得到的所有重量;或求出合并成两堆之后的最小质量差是多少。

其实上一篇谈到的“数字N能否表示成若干个不相同的阶乘的和”就是这个问题的前半部分,前面是采用搜索得到所有可以组成的数量,本文下面采用动态规划来求得所有可以组成的数量。然后再解决该问题的后半部分。

(1)问题前半部分

动态规划:首先是定义好状态,这个问题是求所有可以合并后的和,那么我们就可以利用标号的方法来标记所有可以合并得到的和。数组num[n]表示读入的n堆石子数量。利用bool数组f[N](N为这n堆石子的重量之和),状态f[i] = true 表示可以得到和为i,否则=false,表示不可以得到和为i,有:

边界条件f[0] = true  ---- 尽管没实际意义,但对于DP来说却是必需的

f[i+num[j]] = f[i+num[j]] | f[i]; ---- i满足的条件是:0 <= i <= total – num[j]。方程的意思就是:总数为i的状态可以加上j组成总合为 i+j 的状态。

注意点:由于动态规划需要满足无后效性,那么如果顺推,i+num[j]的顺推必然对后面的造成影响,因此递推的方向需要改成反向,这样就不会影响了:

算法:石子合并的动态规划

过程:调用DP_Stone(n)得到所有标记好的可以组成的和

DP_Stone1 (int n)  {

   int i, j, total

   f[0] = true; total= 420000; // 先置可以组成和为 0total为总数量

   for (j = 0; j < n; j++) {

       for (i = total-num[j]; i >= 0; i--)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值