三种博弈的讲解

  博弈论就是在每种场景下(只有胜利或失败的情况)找到最优决策。
  • 巴什博弈
    只有一堆n个物品,两个人轮流从这堆物品中取物, 规定每次至少取一个,最多取m个。最后取光者得胜。
    在这里 我们引入一个叫奇异局势的概念。当遇到这种局势 无论怎么取 最后都是失败 例如两个物品 每次最多取一个 无论怎么取 都是输 这么来说 我们的目的就很明确了 想办法让我们取完了以后的局面是奇异局势 也就是让对方面对奇异局势 这就是我们的最优决策。
    以下是代码部分
import java.util.Scanner;
public class 博弈论 {
	//八十
	//让第一次取的人赢的方法
       public static void main(String[] Args){
    	   Scanner s = new Scanner(System.in);
           int n = s.nextInt(); //n个物品
           int m = s.nextInt(); //最多取m个
           
           //M+1时第二个取的人赢 无论第一个人取多少都是 而且最多不能取M个所以只要第一次取后剩下的是
           //m+1的整数倍就好了
           int ss = n%(m+1);
           if(ss==0){
        	   System.out.println("必败结局");
           }
           else{
        	   System.out.println("取"+ss);
           }
           
       }
}
  • 威佐夫博弈
    有两堆各若干个物品,两个人轮流从任一堆取至少一个或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
    同样 它也有奇异局势 最优决策也是同样的思路 无疑的 第一个奇异局势是(0,0)而对于每一种局面我们都只有在A堆中取X个 在B堆中取X个 在A堆B堆中同时取X个这三种取法 我们完全可以逆着来 从(0,0)一步步求出所有可能奇异局势 代码如下
import java.util.Scanner;
public class 威佐夫 {
	//让第一次取的人赢
	 public static void main(String[] Args){
  	   //打印必败的奇异局势
		 int [][]sg = new int[20][20];//想更改规模就请更改20这个数值吧
		  
		  sg[0][0] = 0;
	
		 int n = 20;
		 for(int i=0;i<20;i++){
			 for(int j=0;j<20;j++){
				 int win = 0,lose=0;
				 for(int k=1;k<=Math.min(i,j);k++){
					 //System.out.println(Math.min(i, j));
					 if(sg[i-k][j-k]==1)//同时去掉两边的某一个值 是否可能会出现胜利局面
						 //第一个为1的sg[0][1]也出自这里 不符合判断进入else 赋值为1
						 win++;//表示出现了胜利的可能
					 else
					  lose++;//同理 没有胜利局面
				 }	
				 
				 for(int k=0;k<i;k++){
					 if(sg[k][j]==1)//同上 去掉一边的某一个值 是否可能会出现胜利局面
						win++;//表示出现了胜利的可能
					 else
						lose++; //同理 没有胜利局面
	
				 }
				 for(int k=0;k<j;k++){
					 if(sg[i][k]==1)//同上 去掉一边的某一个值 是否可能会出现胜利局面
						 win++;//表示出现了胜利的可能
					 else
					 lose++;//同理 没有胜利局面
				 }
				 if(lose==0) //没有任何胜利局面 必败结局
					 System.out.println("第一个数"+i+" 第二个数"+j); 
				 //此时sg[i][j] = 0
				 else
					 sg[i][j]=1;
				 //为胜利局面
			 }
		 }
		 Scanner s = new Scanner(System.in);
        int A = s.nextInt();
        int B = s.nextInt();
        if(sg[A][B]==1){
        	System.out .println("胜利局面!");
        	if(A==0){
        		System.out.println("请把B拿完");
        	}
        	if(B==0){
        		System.out.println("请把A拿完");
        	}
        	if(A==B){
        		System.out.println("请把AB同时取最大值拿完");
        	}
        	else{
        		for(int i=1;i<B;i++){//不能取完 不然就败了
        			if(sg[A][(B-i)]==0){
        				System.out.println("B堆取"+i+"个");
        				break;
        			}
        		}
        		for(int i=1;i<A;i++){//不能取完 不然就败了
        			if(sg[(A-i)][B]==0){
        				System.out.println("或A堆取"+i+"个");
        			break;
        			}
        		}
        	}
        }
        else{
        System.out.println("必败局面");	      
        }
     }
	 }

关于这题还有很高明的求法 还出现了黄金分割数哦

  • 尼姆博弈
    有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
    思路同上 不过这次我们要用到位运算的知识 我们可以很明显的看出(0,N,N)是一个奇异局势 在这中有 0 ^ N ^N =0 而我们可以推出 当有a ^ b =N 时 (a ,b ,N) 这种情况也是奇异局势 既a ^ b ^ c = 0时 为奇异局势 求最优策略是 即是让最多的一堆等于前两堆的异或所求的值即可 代码如下
import java.util.Scanner;
public class 尼姆 {
	//让先取的赢
        public static void main(String[] args){
        	Scanner s = new Scanner(System.in);
        	int a = s.nextInt();
        	int b = s.nextInt();
        	int c = s.nextInt();
        	if(a>c){
        		int t=0;
        		t = a;
        		a = c;
        		c = t;        		
        	}
        	if(b>c){
        		int t=0;
        		t = b;
        		b = c;
        		c = t;        		
        	}
        	else;
        	if((a^b^c)==0){
        		System.out.println("必败局面");
        	}
        	else{
        		System.out.println("胜利局面!");
        		System.out.println("取最多一堆的"+(c-(a^b))+"个");
        	}
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值