LintCode——巴什博弈(博弈型动态规划)

题目描述

你正在和朋友玩一个游戏:桌子上有一堆石头,每一次你们都会从中拿出1到3个石头。拿走最后一个石头的人赢得游戏。游戏开始时,你是先手。

假设两个人都绝对理性,都会做出最优决策。给定石头的数量,判断你是否会赢得比赛。

举例:有四个石头,那么你永远不会赢得游戏。不管拿几个,最后一个石头一定会被你的朋友拿走。

样例

样例 1:

输入:n = 4 
输出:False
解析:先手取走1,2或者3,对方都会取走最后一个

样例 2:

输入:n = 5 
输出:True
解析:先手拿1个,必胜

思路

解题的关键:分析先手的局面,如果有一招能让对手必败,那就用这招使自己必胜即可,如果没有一招能让对手必败,那当前局面自己就必败。

这是一题用滚动数组来节省空间的博弈型动态规划问题,我开了4个长度的布尔数组就AC了,经过这几次在LintCode上做动态规划题,让我学会了如何使用滚动数组来优化空间的消耗,果然是不用不知道,谁用谁知道哈哈。

 

AC代码

 1 public class Solution {
 2     /**
 3      * @param n: an integer
 4      * @return: whether you can win the game given the number of stones in the heap
 5      */
 6     public boolean canWinBash(int n) {
 7         // Write your code here
 8         if (n == 1 || n == 2 || n == 3) {
 9             // 必胜
10             return true;
11         }
12 
13         // 定义状态:dp[i] 代表当前先手看到的局面是剩下i + 1个石头的输赢情况
14         boolean[] dp = new boolean[4];
15 
16         dp[0] = true;
17         dp[1] = true;
18         dp[2] = true;
19 
20         // 滚动数组
21         int one = -1;
22         int two = 0;
23         int three = 1;
24         int four = 2;
25         for (int i = 3; i < n; i++) {
26             one = (one + 1) % 4;
27             two = (two + 1) % 4;
28             three = (three + 1) % 4;
29             four = (four + 1) % 4;
30             // 枚举拿掉1~3个石头的情况
31             if (!dp[three] || !dp[two] || !dp[one]) {
32                 // 只要有一招让对手必败,那么此时先手就走那招让对手败,自己胜
33                 dp[four] = true;
34             }
35         }
36 
37         return dp[four];
38     }
39 }

 

posted @ 2021-04-06 22:27  没有你哪有我  阅读(187)  评论(0编辑  收藏  举报