Lintcode 394. 硬币排成线

 n 个硬币排成一条线。两个参赛者轮流从右边依次拿走 1 2 个硬币,直到没有硬币为止。拿到最后一枚硬币的人获胜。

请判定 第一个玩家 是输还是赢?

有点博弈论的意思

public boolean firstWillWin(int n) {
    // write your code here
    boolean[] dp = new boolean[n+1];
    dp[0] = false;
    dp[1] = true;
    dp[2] = true;
    dp[3] = false;
    for (int i = 4; i < n+1; i++) {
        dp[i] =  ((dp[i-2] && dp[i-3]) || (dp[i-3]) && dp[i-4]);
    }

    return dp[n];
}
public boolean firstWillWin1(int n) {
    if(n == 0) return false;

    boolean dp[] = new boolean[n+1];
    dp[0] = false;
    dp[1] = true;

    for(int i =2; i<=n; i++) {
        dp[i] = !dp[i-1] || !dp[i-2];
    }

    return dp[n];
}

public boolean firstWillWin2(int n) {
    // write your code here
    return n%3==0?false:true;

第一想法其实由观察规律得来。。。可以看到数据肯定可以保证3个一轮,因为你拿1个,我就2个,你拿2个,我就1个,也就是说如果是3的倍数,肯定是后手赢,先手可以拿1-2个把总数改成3的倍数。

这道题是典型的博弈论,显然每次我们都是三个三个循环,如果我先拿,我拿一个,对方可以拿两个,我拿两个,对方可以拿一个,所以如果总数是三的倍数的话,肯定是对方获胜,所以答案就出来了,n不能是三的倍数

 

无论是从博弈论还是从dp的角度,都是从观察规律出发,而自己的动态规划就粗暴一点,就是a拿一个b拿一个的情况,a拿一个,b拿两个的情况与a拿两个b拿一个的情况,a拿两个b拿两个的情况的或,只要前一次博弈中 无论a拿了一个还是拿了两个,b拿一个还是两个都改变不了a赢得局面

summary:1、暴力动态规划法,列出前一轮中的所有情况

2、引入编程博弈论的认知!如果是a拿一个b拿三个这种,就应该是n%4

猜你喜欢

转载自blog.csdn.net/qq_38702697/article/details/82956796
今日推荐