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枚后手胜利也是这个道理。

  • 相关阅读:
    Hibernate save, saveOrUpdate, persist, merge, update 区别
    Eclipse下maven使用嵌入式(Embedded)Neo4j创建Hello World项目
    Neo4j批量插入(Batch Insertion)
    嵌入式(Embedded)Neo4j数据库访问方法
    Neo4j 查询已经创建的索引与约束
    Neo4j 两种索引Legacy Index与Schema Index区别
    spring data jpa hibernate jpa 三者之间的关系
    maven web project打包为war包,目录结构的变化
    创建一个maven web project
    Linux下部署solrCloud
  • 原文地址:https://www.cnblogs.com/gujiewei/p/9670565.html
Copyright © 2011-2022 走看看