464. 我能赢吗
思路:
直接搜索即可
主要难点在于考虑搜索函数的状态,观察注意到最多只有20个整数,我们可以用一个
int(32位)完全表示这个整数,一个int的第i位为0则代表这个整数i还没有被拿走,反之则已经拿走假设我们有函数f,可以返回一个状态下能否必胜,那么对于A(博弈者)来说,f的返回值就是该状态下,穷尽所有可行的操作,能不能胜利
最后我们再用一个mp存储之前算出的结果,避免重复计算
class Solution {
public:
int mp[2<<21]; // 0 为未搜索,1为胜,2为败
bool find(int status,int sum,int n){ // find 返回这种情况下穷尽所有操作能不能赢
if(mp[status]!=0){// 如果status已经被搜索了,返回结果
return mp[status]==1;
}
if(sum<=0){ // 如果和已经超过值了,则说明已经输了
mp[status]=2;
return false;
}
for(int i=1;i<=n;i++){
if(((status>>i)&1)==0) // 如果这个数字还没有被拿走
if(find(status|(1<<i),sum-i,n)==0){ // 尝试拿走他,看看这个状态是不是对方的必败态
mp[status]=1;
return true;
}
}
mp[status]=2;
return false;
}
bool canIWin(int mx, int desiredTotal) {
if(mx*(mx+1)/2<desiredTotal) return false; // 如果所有数字之和都超不过desiredTotal,则都败
if(!desiredTotal) return 1; // 如果一开始desiredTotal则说明一开始就赢了
// 前面两行是特判
return find(0,desiredTotal,mx);
}
};