取石子游戏(威佐夫博弈的整理)和动态规划

问题描述:有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。

看起来这很像一种益智游戏,可以依靠枚举来进行尝试,从而找到最终答案,但其中蕴含着一个很有意思的规律,使得这个问题可以依靠代码来运算,那个有趣的规律就是威佐夫博弈.

这个博弈中有个概念叫做奇异局势,就是当是奇异局势时,先拿着必输,当不是时,则反之。这个结论的应用非常简单了,但是如何证明一个局势是奇异局势,就非常的复杂。

奇异局势的性质

1。任何自然数都包含在一个且仅有一个奇异局势中。

由于a[k]是未在前面出现过的最小自然数,所以有a[k] > a[k-1] ,而 b[k]= a[k] + k > a[k-1] + k > a[k-1] + k - 1 = b[k-1] > a[k-1] 。所以性质1成立。

2。任意操作都可将奇异局势变为非奇异局势。

事实上,若只改变奇异局势(a[k],b[k])的某一个分量,那么另一个分量不可能在其他奇异局势中,所以必然是非奇异局势。如果使(a[k],b[k])的两个分量同时减少,则由于其差不变,且不可能是其他奇异局势的差,因此也是非奇异局势。

3。采用适当的方法,可以将非奇异局势变为奇异局势。

假设面对的局势是(a,b),若 b = a,则同时从两堆中取走 a 个物体,就变为了奇异局势(0,0);如果a = a[k] ,b > b[k] 那么,取走b - b[k]个物体,即变为奇异局势;如果 a = a[k] , b < b[k] 则同时从两堆中拿走a-a[b-a](注:这里b-a是a的下标, 不是a*(b-a)) 个物体变为奇异局势( a[b-a], b-a+a[b-a]);如果a > a[k] ,b= a[k] + k 则从第一堆中拿走多余的数量a - a[k] 即可;如果a < a[k] ,b= a[k] + k,分两种情况,第一种,a=a[j] (j < k)从第二堆里面拿走 b - b[j] 即可;第二种,a=b[j] (j < k)从第二堆里面拿走 b - a[j] 即可。

结论:两个人如果都采用正确操作,那么面对非奇异局势,先拿者必胜;反之,则后拿者取胜。

最后利用beatty序列得出判断局势是否为奇异局势的式子:ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,...n 方括号表示取整函数)   

所以一旦两堆石子确定,两边都采取正确方法,结局就已经唯一确定。

     

 动态规划

我们从例题数字三角形来体会动态规划的意义,有一个金字塔型的的三角形数字塔,每一层都比上一层多一个,除最后一层,每一层每一个都有两个“脚”相对应,如何选择哪只“脚”,使得从上往下一串数字之和最大,这里就用到了动态规划,从下往上,显然每次都会生成两个可能,每次都挑选最大的相加,最后最大的就是最上面那个数字。

 

 #include<iostream>

#include<algonithm>

using namespace std;

#define MAX 101

int D[MAX][MAX];

int n; int *maxsum;

int main(){

int i,j;

cin>>n;

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

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

                  cin>> D[i][j];             /*数字输入*/

maxsum=D[n];

for( int i=n-1;i>=1;--i)

      for(int j=1;j<=i;++j)

            maxsum[j] = max(maxsum[j],maxsum[j+1])+D[i][j];          /*  递归转化为递推*/

cout << maxsum[1]<<end1;                              /*最终输出最终结果30*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值