硬币游戏1(博弈入门)

题目:

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;
}

猜你喜欢

转载自www.cnblogs.com/shuaihui520/p/9553259.html