zoukankan      html  css  js  c++  java
  • [java,2019-01-28] 枪手博弈,谁才是最后赢家

    什么是枪手博弈:

      枪手博弈指彼此痛恨的甲乙丙三个枪手准备决斗。甲枪法最好,十发八中。乙枪法次之,十发六中。丙枪法最差,十发四中。假设他们了解彼此实力,也能做出理性判断。

      问题一:如果三人同时开枪,并且每人每次只发一枪。若干轮枪战后,谁活下来的机会大?

      问题二:如果三人轮流开枪,并且由枪法最差的丙先开枪,他该怎么做?

    问题一:

    分析:

      3个人同时开枪,则枪手开枪的同时也可能被射死,4种情况,场上分别剩余(3,2,1,0)人

    1)场上剩余3人,此时a(甲)一定向b(乙)射击,b一定向a射击,c(丙)可能向a射击或向空射击

    2)场上剩余2人,互射,无其他可能

    3)场上剩余1人,最后的胜利者

    4)场上剩余0人,全部死亡

    抽象出枪手模型

     1 public class Hackbuteer {
     2     private int state=1; //存活状态,1存活,0死亡
     3     private double shot_rate; //命中率
     4     public Hackbuteer(double shot_rate){
     5         this.shot_rate=shot_rate;
     6     }
     7     public int getState() {
     8         return state;
     9     }
    10     public void setState(int state) {
    11         this.state = state;
    12     }
    13     public double getShot_rate() {
    14         return shot_rate;
    15     }
    16     public void setShot_rate(double shot_rate) {
    17         this.shot_rate = shot_rate;
    18     }
    19     public boolean shot(Hackbuteer target) {
    20         double rand = Math.random();
    21         if(rand<shot_rate){ //随机数小于命中率,表示命中
    22             target.state=0; //目标死亡
    23             return true;
    24         }
    25         return false;
    26     }   
    27 }

     模拟多次(100w)射击,用频率估算概率,代码如下:

     1 public class HackbuteerTest {
     2     public static void main(String[] args) {
     3         int a_count=0;  //a存活次数
     4         int b_count=0;  //b存活次数
     5         int c_count=0;  //c存活次数
     6         for(int i=0;i<1000000;i++){
     7             Hackbuteer a=new Hackbuteer(0.8);
     8             Hackbuteer b=new Hackbuteer(0.6);
     9             Hackbuteer c=new Hackbuteer(0.4);
    10             while(true){
    11                 int all_state=a.getState()+b.getState()+c.getState(); //场上存活状态
    12                 if(all_state==3){ //3人都存活
    13                     a.shot(b);
    14                     b.shot(a);
    15                     //c.shot(a); //c向a射击;若模拟向空射击,则注释此行
    16                 }else if(all_state==2){ //1人死亡,2人存活
    17                     if(a.getState()==0){
    18                         b.shot(c);
    19                         c.shot(b);
    20                     }
    21                     if(b.getState()==0){
    22                         a.shot(c);
    23                         c.shot(a);
    24                     }
    25                     if(c.getState()==0){
    26                         b.shot(a);
    27                         a.shot(b);
    28                     }
    29                 }else if(all_state==1   //仅有一人存活
    30                         || all_state==0   //无人存活
    31                         ){   
    32                     if(a.getState()==1){
    33                         a_count++;
    34                     }
    35                     if(b.getState()==1){
    36                         b_count++;
    37                     }
    38                     if(c.getState()==1){
    39                         c_count++;
    40                     }
    41                     break;
    42                 }
    43                 
    44             }
    45         }
    46         System.out.println("a存活--"+a_count);
    47         System.out.println("b存活--"+b_count);
    48         System.out.println("c存活--"+c_count);
    49         System.out.println("无人存活--"+(1000000-a_count-b_count-c_count));
    50         
    51     }
    52 }

    结果:

    c向a射击,c向空射击

    所以对于c来说,在同时开枪的情况下,c应该向a开枪,而不是向空开枪。

    PS:以上结果仅代表实验100w次的频率,不完全代表概率。

    问题二:

    分析:

    3人轮流开枪,c先开枪,依然是2种方案(向a射击,向空射击),代码如下:

     1 public class HackbuteerTest2 {
     2     public static void main(String[] args) {
     3         int a_count=0;  //a存活次数
     4         int b_count=0;  //b存活次数
     5         int c_count=0;  //c存活次数
     6         for(int i=0;i<1000000;i++){
     7             Hackbuteer a=new Hackbuteer(0.8);
     8             Hackbuteer b=new Hackbuteer(0.6);
     9             Hackbuteer c=new Hackbuteer(0.4);
    10             while(true){
    11                 //c存活,开枪策略1,优先射击a
    12                 if(c.getState()==1){
    13                     if(a.getState()==1){
    14                         c.shot(a);
    15                     }else if(b.getState()==1){
    16                         c.shot(b);
    17                     }
    18                 }
    19                 //c存活,开枪策略2,当a,b都存活时,不射击任何人
    20 //                if(c.getState()==1){
    21 //                    if(a.getState()==0 && b.getState()==1){
    22 //                        c.shot(b);
    23 //                    }else if(a.getState()==1 && b.getState()==0){
    24 //                        c.shot(a);
    25 //                    }
    26 //                }
    27                 
    28                 //a存活,开枪策略,优先射击b
    29                 if(a.getState()==1){
    30                     if(b.getState()==1){
    31                         a.shot(b);
    32                     }else if(c.getState()==1){
    33                         a.shot(c);
    34                     }
    35                 }
    36                 //b存活,开枪策略,优先射击a
    37                 if(b.getState()==1){
    38                     if(a.getState()==1){
    39                         b.shot(a);
    40                     }else if(c.getState()==1){
    41                         b.shot(c);
    42                     }
    43                 }
    44                 
    45                 if(a.getState()+b.getState()+c.getState()==1){ //仅有一人存活
    46                     if(a.getState()==1){
    47                         a_count++;
    48                     }
    49                     if(b.getState()==1){
    50                         b_count++;
    51                     }
    52                     if(c.getState()==1){
    53                         c_count++;
    54                     }
    55                     break;
    56                 }
    57                 
    58             }
    59         }
    60         System.out.println("a存活--"+a_count);
    61         System.out.println("b存活--"+b_count);
    62         System.out.println("c存活--"+c_count);
    63     }
    64 }

    结果:

    c向a射击,c向空射击

    显然,此时c应该向空射击,而不是向a射击

    PS:当射击顺序为(c-b-a时,结论依然如此)

    结论:

    火并也要按照基本法,同时开枪有1/4-1/3的概率全部玩完(你是不是以为我要说什么实力很重要,选择很重要,背叛与忠诚?)

  • 相关阅读:
    Windows Server 2012配置开机启动项
    Windows Server 2019 SSH Server
    NOIP2017 senior A 模拟赛 7.7 T1 棋盘
    Noip 2015 senior 复赛 Day2 子串
    Noip 2015 senior复赛 题解
    Noip 2014 senior Day2 解方程(equation)
    Noip 2014 senior Day2 寻找道路(road)
    Noip 2014 senior Day2 无线网络发射器选址(wireless)
    Noip2014senior复赛 飞扬的小鸟
    Noip 2014 senior 复赛 联合权值(link)
  • 原文地址:https://www.cnblogs.com/shijt/p/10331372.html
Copyright © 2011-2022 走看看