码迷,mamicode.com
首页 > 其他好文 > 详细

【LeetCode】一种博弈思路 minimax(共5题)

时间:2019-02-20 13:12:38      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:pen   ica   return   guess   strong   空间   问题   closed   lap   

【375】Guess Number Higher or Lower II 

 

【464】Can I Win (2019年2月20日,谷歌tag,M)

给了一个1-100的游戏,游戏规则是,两个选手,player1每次从1-100中抽取一个数字,player2每次也从1-100中抽取一个数字,不能重复抽取相同的数字。直到某个player抽取到一个数,所有轮次中每个player抽取的数字加和大于等于target(target是提前给定的)。问player1能不能赢这个游戏。

本题的题目意思是把100换成一个变量叫做 maxChoosableInteger。问 player1 能不能赢这个游戏。

题解:这是一棵博弈树的问题。解空间如下图:

技术图片

裸的dfs搜索方法如下:对于当前的局面,我们尝试用一个没有用过的数作为当前的解,然后dfs到下一个局面。

如果下个局面返回了false,就是对手不能赢,那我肯定非常高兴的马上返回了true,因为这个局面我能赢。(注意返回的时候要把当前局面用过的数字清空。回溯。不能忘。

但是如果下个局面返回了true,我就会认真反思自己,然后后悔当前局面的走法(是的,就是这么的无赖)去换一种新的走法。

那么对于当前局面的前一个局面来说,对手看到我返回了true,那他也可以反悔啊,他内心os:老子也不这么走了,我也要换一个走法。于是他就继续遍历他解空间的下一个解,直到他在当前空间找到了一个解,这个解能让他在当前空间赢,或者他找遍了所有的可能解,都赢不了,他只好认输,"我在当前空间赢不了,我返回false"。

技术图片
 1 class Solution {
 2 public:
 3     bool canIWin(int maxChoosableInteger, int desiredTotal) {
 4         if (desiredTotal <= 0) {return true;}
 5         if (maxChoosableInteger * (maxChoosableInteger + 1) / 2 < desiredTotal) {return false;}
 6         string used(maxChoosableInteger, 0);
 7         int sum = 0;
 8         return canIWin(maxChoosableInteger, desiredTotal, sum, used);
 9     }
10     bool canIWin(int maxChoosableInteger, int desiredTotal, int sum, string& used) {
11         if (sum >= desiredTotal) {return false;}
12         for (int i = 1; i <= maxChoosableInteger; ++i) {
13             if (used[i-1] == 1) { continue; } //如果当前的数用过了,那么就换下一个能用的数
14             used[i-1] = 1;
15             if (canIWin(maxChoosableInteger, desiredTotal, sum + i, used) == false) {
16                 //到这里需要回溯。如果下一个局面为false的话,就说明当前局面能赢。
17                 //但是你想象一下如果你是一个玩家,当对手告诉你这个局面对手能赢的时候,你会怎么做,
18                 //肯定是返回到一个有一个解-对手不能赢的层次,然后去dfs那个解空间。
19                 used[i-1] = 0; 
20                 return true;
21             }
22             used[i-1] = 0;
23         }
24         return false;
25     }
26 };
View Code

再加上可以记忆化或者状态压缩的技巧。用个memo。

技术图片
 1 class Solution {
 2 public:
 3     bool canIWin(int maxChoosableInteger, int desiredTotal) {
 4         if (desiredTotal <= 0) {return true;}
 5         if (maxChoosableInteger * (maxChoosableInteger + 1) / 2 < desiredTotal) {return false;}
 6         string used(maxChoosableInteger, 0);
 7         int sum = 0;
 8         return canIWin(maxChoosableInteger, desiredTotal, sum, used, 0);
 9     }
10     unordered_map<string, bool> memo;
11     bool canIWin(int maxChoosableInteger, int desiredTotal, int sum, string& used, int player) {
12         if (sum >= desiredTotal) {return false;}
13         if (memo.find(used) != memo.end()) {return memo[used];}
14         string key = used;
15         memo[key] = false;
16         for (int i = 1; i <= maxChoosableInteger; ++i) {
17             if (used[i-1] == 1) { continue; }
18             used[i-1] = 1;
19             if (canIWin(maxChoosableInteger, desiredTotal, sum + i, used, 1 - player) == false) {
20                 memo[key] = true;
21                 used[i-1] = 0;
22                 return true;
23             }
24             used[i-1] = 0;
25         }
26         return false;
27     }
28 };
View Code

 

【486】Predict the Winner 

 

【843】Guess the Word 

 

913】Cat and Mouse 

【LeetCode】一种博弈思路 minimax(共5题)

标签:pen   ica   return   guess   strong   空间   问题   closed   lap   

原文地址:https://www.cnblogs.com/zhangwanying/p/9964702.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!