博弈论-取石子

文章目录

  • 引言
  • Nim游戏
  • 巴什博弈
  • 威佐夫博弈
  • 斐波那契博弈

引言

本文主要简单介绍博弈论中的著名问题–取石子,成为获胜者的条件都是取走最后一个石子

Nim游戏

关键词:N堆、第i堆石子有Ai个、每次可以任选一堆石子,至少取走1个石子

给定N堆石子,第i堆石子有Ai个。两名玩家轮流行动,每次可以任选一堆,取走任意多个石子,可把一堆取光,但不能不取。取走最后一个石子获胜。两人都采取最优策略,问先手是否必胜。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int ans = 0,a,n;
        Scanner scanner=new Scanner(System.in);
        n= scanner.nextInt();//石子堆数
        while(n>0){
            a=scanner.nextInt();//每一堆石子个数
            ans^=a;
            n--;
        }
        if(ans==0) System.out.println("No\n");//表示先手输
        else System.out.println("Yes\n");//表示先手赢
    }

}

巴什博弈

关键词:1堆石子、取得石子个数为[1,m]

有 1 堆石子,总个数是 n ,两名玩家轮流在石子堆中拿石子,每次至少取 1 个,至多取 m 个。取走最后一个石子的玩家为胜者。

结论: n%(m+1)=0时,先手必败;否则先手必胜。
证明:
①当m>=n时,显然先手必胜。
②当m+1=n时,无论先手取多少个,后手都能一次全部取完,先手必败。
③当n%(m+1)=0时,假设先手取了x个,那么后手一定可以取(m+1)-x个。因此无论先手怎么取,聪明的后手都会使得最后的物品总数量是m+1的倍数,慢慢的就会到②的情况,因此先手必败。
④当n%(m+1)!=0时,先手就可以先取n%(m+1)个物品,这样就会丢下n%(m+1)=0的局面给对面,那么后手必败,先手必胜

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int n,m;
        Scanner scanner=new Scanner(System.in);
        n = scanner.nextInt();
        m=scanner.nextInt();
        if(n%(m+1)==0) System.out.println("No\n");//表示先手输
        else System.out.println("Yes\n");//表示先手赢
    }

}

威佐夫博弈

关键词:两堆石子、每次可以在一堆中取,或者从两堆中取走相同个数的石子(数量不限)

有两堆石子,石子数可以不同。两人轮流取石子,每次可以在一堆中取,或者从两堆中取走相同个数的石子,数量不限,取走最后一个石头的人获胜。

import java.util.Scanner;

import static java.lang.Math.sqrt;

public class Main {
    public static void main(String[] args) {
        int n,m;
        Scanner scanner=new Scanner(System.in);
        n = scanner.nextInt();
        m=scanner.nextInt();
        if(n>m){
            int temp=n;
            n=m;
            m=temp;
        }
        int ans= (int) ((m-n)*((1.0+sqrt(5))/2.0));
        if(ans==n) System.out.println("No\n");//表示先手输
        else System.out.println("Yes\n");//表示先手赢
    }

}

斐波那契博弈

关键词:一堆石子、先手第一次取的石子数为[1,n)、之后每次取得石子数为[1,2*对手上一次取的石子数]

一堆个数为n(n≥2)的石子,游戏双方轮流取石子,规则如下:
先手不能在第一次把所有的石子取完,至少取1颗;
之后每次可以取的石子数至少为1,至多为对手刚取的石子数的2倍。

结论:
当且仅当石子数为斐波那契数时,先手必败。

import java.util.HashMap;
import java.util.Scanner;

import static java.lang.Math.sqrt;

public class Main {
    static int[] f = new int[1005];
    static HashMap<Integer,Integer> map=new HashMap();

    public static void main(String[] args) {
        int n;
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        solve();
        if (map.containsKey(n)) System.out.println("No");//表示先手输
        else System.out.println("Yes");//表示先手赢
    }

    //构造斐波那契数列
    public static void solve() {
        f[1] = f[2] = 1;
        for (int i = 3; i <= 1000; ++i) {
            f[i] = f[i - 1] + f[i - 2];
            map.put(f[i],1);
        }
    }
}

你可能感兴趣的:(数据结构与算法,java,算法,数据结构)