zoukankan      html  css  js  c++  java
  • 拿硬币——动态规划

    拿硬币


    Question: 有10个硬币,我和你按顺序拿,每次可以拿1、2或者4个,拿到最后一个硬币的人输,你怎么确保自己可以获胜

    (这个问题的有一个前提:双方都想赢,并且当遇到能赢的情况时,他们能做出正确的决策而不是随便决策)
    这种问题,可以从简单情况先想起,:

    • 没有硬币剩下,则默认该轮次的人胜利。

    • 剩下一个硬币时,先手拿硬币的人输,后手赢;

    • 剩下两个硬币时,先手的人一下子拿两个,则先手输。
      先手的人拿一个,刚才推过,可以知先手赢。
      所以,面对这种情况,先手时你可以认为你赢定了。、

    • 剩下三个硬币时,先手的人如果只拿一个,剩下两个硬币,则我们刚才推过,这种情况你会输。
      先手的人如果拿两个,剩下一个硬币,你赢。
      所以,对于这种情况,先手的人也赢定了。

    • 剩下四个硬币时,先手的人拿四个,则先手人会输。
      先手如果拿两个,我们刚才推过,先手也输定了。
      先手如果拿一个,也是上面推过,先手输定了。

    …..

    依此下来,我们是不是发现,对于固定的剩余硬币数量,先手还是后手直接可以决定你的输赢。
    其实,这是利用了动态规划的思想。
    我们假设f(i)表示结果,0表示输,1表示赢。
    当轮到你去取硬币时,我们假设面前有i枚硬币,你有三种取法(即取 1,2,4),当你取完就该对手取,如果说三种取法里面只有有一个取法能够让对手最后输掉,那么可以说你就赢了。
      

    写成状态转移方程:
         f(i)=(f(i-1)==0 || f(i-2)==0 || f(i-4)==0 )     

    状态推算:
    f(0)=1
    f(1)=0
    f(2)=1
    f(3)=1
    f(4)=0
    f(5)=1
    f(6)=1
    f(7)=0
    f(8)=1
    f(9)=1
    f(10)=0
    

    所以,对于10枚硬币,先手拿不管怎么拿必输,因为后面的局面完全可以被后手的人掌握主动权,所以你要后手拿,然后你就可以根据表格获得制胜的策略。

    10枚可以自己去推,我们简单来推测下,为什么7枚后手怎么赢。

    1. 如果对方拿4枚,剩3枚,将i==3带入公式,我们发现 f(3-1)==0,所以我们取 1 枚,剩下一枚,胜利!
    2. 如果对方拿2枚,剩下5枚,将i==5带入公式,发现f(5-1)==0,所以我们取 1 枚,剩下 4 枚,我们在前面推过,面对4枚对方先手,他输定了。
    3. 如果对方拿1枚,剩6枚,将i==6带入公式,发现f(6-2)==0,所以取 2 枚,又剩下四枚,同样的情况,你赢定了。

      所以,7枚后手具体是这样,10枚后手胜利也是这个道理。

  • 相关阅读:
    git shell自动打tag
    git 获取最新的匹配到的tag
    centOS debian ubuntu 一键安装 docker 教程
    git将当前分支的修改推到其他分支
    MusicPlayer2
    Ventoy 多合一启动盘制作工具神器
    electron-builder 下载 electron过慢或报错的解决办法
    解决npm install 报错“npm WARN pug-loader@2.4.0 requires a peer of pug@^2.0.0 but none is installed. You must install peer dependencies yourself.“
    全能笔记软件 Notion 的“中国版" wolai
    Your branch is behind 'origin/master' by N commits, and can be fast-forwarded 解决方法
  • 原文地址:https://www.cnblogs.com/gujiewei/p/9670565.html
Copyright © 2011-2022 走看看