zoukankan      html  css  js  c++  java
  • 硬币游戏 (博弈入门)

    题目:

    A 和 B 在玩一个游戏,给定K个数字a1,a2,a3...ak ; 一开始有x个硬币 ; A 和 B 轮流取硬币。每次所取硬币的枚数一定在a1,a2,a3..ak ; 里面,A 先取 , 取走最后一枚的获胜 , 两个人都采取最优的策略,谁会WIN ?

    分析:

    博弈论的关键就在于找出必胜态 和 必败态 ; 

    1.既然取关了硬币就是获胜 , 那就是说到自己的时候没有硬币了,就是输了 ; 则j=0 ; 时是必败态 ; 

     

    2.如果对于某个i(1<=i<=k) , j-ai是传说中的必败态 , 那 j 就是必胜态 ; (当只有j枚硬币的时候 , 只要拿走a1枚对手就输了,那就是等于我赢了)

     

    3.如果对于任意的i(1<=i<=k) , j-ai 都是必胜态,j就是必败态 ; (无论怎么取都是对手赢,那就是输)

    难以理解的话,可以把 j 看成是当前的状态 , j-ai 是上一个状态 ; 这样可以找到j

    依靠这些规则,采用动态规划的思想按照j从小到大的顺序计算必胜与必败 ; 到时我们只要看x是必胜还是必败即可 ; 

    #include<stdio.h>
    int x,k,a[20001];
    bool win[20001];
    int main( )
    {
        scanf("%d %d",&x,&k);
        for(int i=0 ; i<k ; i++)
        scanf("%d",&a[i]);
    
        win[0] = false;//到自己的时候没有了就输了;
        for(int j=1 ; j<=x ; j++)
        {
            win[j] = false;
            for(int i=0 ; i<k ; i++)
            {
                win[j] |=a[i]<=j && !win[j-a[i]];
            }
        }
        if(win[x])
        puts("A");
        else
        puts("B");
        return 0;
    }

    自己敲的

    #include<stdio.h>
    int x,k,a[20001];
    bool win[20001];
    int main( )
    {
        scanf("%d %d",&x,&k);
        for(int i=0 ; i<k ; i++)
        scanf("%d",&a[i]);
    
        win[0] = false;//到自己的时候没有了就输了;
        for(int j=1 ; j<=x ; j++)
        {
            win[j] = false;
            for(int i=0 ; i<k ; i++)
            {
                if(a[i]<=j)
                {
                    if(win[j-a[i]]==false)
                    win[j]=true;
                }
    
            }
        }
        if(win[x])
        puts("A");
        else
        puts("B");
        return 0;
    }

    题目

    意思就是两个人轮流拿硬币,Alice先拿,Alice拿的时候可以选择拿走一个或者拿走相邻的两个,谁拿完最后的石子胜利。

    #include<stdio.h>
    int main( )
    {
        int n ;
        scanf("%d",&n);
        if(n<=2)
        puts("Alice");
        else
        puts("Bob");
        return 0;
    }

    题目:

    A 和 B 在玩游戏,给k个数字a1 , a2 , ... , ak ; 一开始有n堆硬币 , 每一堆有 xi 枚 。 A 和 B 轮流选出一堆硬币 ,从中取出硬币 , 每次所取硬币的枚数一定在a1 , a2 , a3 ,...., ak ; 里面,A先取,取光硬币的一方获胜 。 

     

    分析:这里引入一个概念 Grundy , 利用这个东西,很多游戏都可以转换为Nim>

    只有一堆石头的情况

    复制代码
    int grundy(int x){
        集合S={};
        for(j=1:k){
            if(a_j<=x) 将grundy(x-a_j)加到S集合中 
        } 
        return 最小的不属于S的非负整数 
    }
    复制代码

    rundy值:除(任意一步所能转移到 的状态  的Grundy值 )以外的最小非负整数,这样的Grundy值,和Nim中的一个石子堆类似,有如下性质:

    mex{0,1,2}=3;mex{ 1, 2}=0 ; mex{ 2, 3}=1

    1.Nim中有x颗石子的石子堆,能转移成有0,1,……,x-1堆石子的石子堆

    2.从Grundy值为x的状态出发,可以转移到Grundy值为0,1,……,x-1的状态。 

     

    Nim:

    所有石子堆的石子数xi的XOR

    x1 XOR x2 XOR …XOR xk

    为0必败,为1必胜

     

    Grundy值等价于Nim中石子数,所以对于Grundy的情况:

    所有硬币堆的Grundy的值

    grundy(x1)  XOR  grundy(x2)  XOR …… XOR grundy(xn)

     为0必败,为1必胜。

    #include <cstdio>
    #include <set>
    #include <algorithm>
    #define maxn 105
    #define maxk 105
    using namespace std;
    int N,K,X[maxn],A[maxk];
    int grundy[maxn+1];
     
     
    void solve(){
        //轮到自己剩0的时候必败 
        grundy[0]=0;            
        
        //计算grundy 
        int max_x=*max_element(X,X+N);
        for(int j=1;j<=max_x;j++){
            set<int> s;                //存储当前的状态 
            for(int i=0;i<K;i++){
                if(A[i]<=j) s.insert(grundy[j-A[i]]);
            }
            int g=0;                //寻找当前状态的最小排斥 
            while(s.count(g)!=0) g++;
            grundy[j]=g;
        }    
        int ans=0;
        for(int i=0;i<N;i++) ans^grundy[X[i]];
        
        if(ans!=0)    puts("Alice");
        else puts("Bob");
        
    }
     
     
    int main(){
        scanf("%d%d",&N,&K);    
        for(int i=0;i<N;i++){
            scanf("%d",&A[i]);
        }
        for(int j=0;j<K;j++){
            scanf("%d",&X[j]);
        }
        solve();
        
        return 0;
    } 
     
  • 相关阅读:
    (转)Silverlight从程序集读取xaml文件
    阻止jQuery事件冒泡
    如何避免JQuery Dialog的内存泄露(转)
    VS2010 好用的javascript扩展工具
    C#计时器
    Silverlight初体验之设置启动页面
    javascript调用asp.net后置代码方法
    应用程序工程文件组织重要性
    javascript中字符串转化为json对象
    jQuery EasyUI
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9553259.html
Copyright © 2011-2022 走看看