LeetCode 464 Can I Win 题解

题意简述:给定两个值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 是可接受的。

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);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值