LeetCode 464 Can I Win 题解
2017-04-27 18:43
344 查看
题意简述:给定两个值n和desiredTotal,要求两位玩家从整数1,2,……,n中依次取数,每个数只能取一次,每个取出的数都会加到一个和数上,最先使和数大于或等于desiredTotal的玩家获胜。问玩家1(先取数的)是否必胜。假设两位玩家都会作出最优选择。
输入:两个值n和desiredTotal。
输出:一个bool值,表示玩家1是否获胜。
示例:对于n=10和desiredTotal=11,玩家1必败,因为无论取1到10哪个数,玩家2都能再取一个数使和达到11。
题解:
采用dfs+map辅助记忆化搜索。使用二进制串记录当前状态下每个数有没有被拿(数可用为1,不可用为0)。dp(bits, remain)为true,当且仅当对于bits里面所有可用的i,存在dp(bits & ~(1 << i), remain-i)为false。简单的解释:对于当前状态,只要在所有的取法中存在至少一种取法使对方必败,那么这个状态是必胜的。终结状态是remain <= 0,这意味着已经取的数之和已经超过desiredTotal,因而是必败状态。
使用unorder_map记录dfs过程中产生中间状态dp的值。注意unorder_map的key值可以只用bits,这是因为remain可以通过desiredTotal减去已取的数(bits对应位为1)之和得到。
算法实现如下,空间复杂度是O(2n),因为状态数就是2n。在这题中n<=20,因此2n是可接受的。
输入:两个值n和desiredTotal。
输出:一个bool值,表示玩家1是否获胜。
示例:对于n=10和desiredTotal=11,玩家1必败,因为无论取1到10哪个数,玩家2都能再取一个数使和达到11。
题解:
采用dfs+map辅助记忆化搜索。使用二进制串记录当前状态下每个数有没有被拿(数可用为1,不可用为0)。dp(bits, remain)为true,当且仅当对于bits里面所有可用的i,存在dp(bits & ~(1 << i), remain-i)为false。简单的解释:对于当前状态,只要在所有的取法中存在至少一种取法使对方必败,那么这个状态是必胜的。终结状态是remain <= 0,这意味着已经取的数之和已经超过desiredTotal,因而是必败状态。
使用unorder_map记录dfs过程中产生中间状态dp的值。注意unorder_map的key值可以只用bits,这是因为remain可以通过desiredTotal减去已取的数(bits对应位为1)之和得到。
算法实现如下,空间复杂度是O(2n),因为状态数就是2n。在这题中n<=20,因此2n是可接受的。
class Solution { private: unordered_map<unsigned long, bool> mymap; int _maxInteger; bool dp(bitset<20>& mybit, int remain) { if(mymap.find(mybit.to_ulong()) != mymap.end()) return mymap[mybit.to_ulong()]; if(remain <= 0) { mymap[mybit.to_ulong()] = false; return false; } for(int i = 1;i <= _maxInteger;i++) { if(!mybit[i-1]) { mybit.set(i-1); bool temp = dp(mybit, remain-i); mybit.reset(i-1); if(!temp) { mymap[mybit.to_ulong()] = true; return true; } } } mymap[mybit.to_ulong()] = false; return false; } public: bool canIWin(int maxChoosableInteger, int desiredTotal) { _maxInteger = maxChoosableInteger; bitset<20> mybit; mybit.reset(); if(desiredTotal <= 0) return true; if((1+maxChoosableInteger)*maxChoosableInteger/2 < desiredTotal) return false; return dp(mybit, desiredTotal); } };
相关文章推荐
- [leetcode 464]Can I Win
- Leetcode 464 can i win
- leetcode464 Can I Win
- leetcode 464 Can I Win
- [LeetCode] Can I Win 我能赢吗
- 464 Can I Win
- 464. Can I Win**
- Leetcode: Can I Win
- [LeetCode] Can I Win
- LeetCode13 Can I win
- LeetCode Can I Win
- LeetCodet题解--21. Merge Two Sorted Lists(合并两个排序好的链表)
- LeetCode题解:Invert Binary Tree
- leetcode题解-451. Sort Characters By Frequency
- 【LeetCode题解】309. Best Time to Buy and Sell Stock with Cooldown
- LeetCode题解:Pascal's Triangle II
- leetcode题解-13. Roman to Integer && 14. Longest Common Prefix && 20. Valid Parentheses
- LeetCode题解:Lowest Common Ancestor of a Binary Search Tree
- LeetCode题解——Reverse Linked List
- LeetCode题解 第九周