[Leetcode464]我能赢吗?——状态压缩+dfs

1.题目

在 "100 game" 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和 达到或超过  100 的玩家,即为胜者。

如果我们将游戏规则改为 “玩家 不能 重复使用整数” 呢?

例如,两个玩家可以轮流从公共整数池中抽取从 1 到 15 的整数(不放回),直到累计整数和 >= 100。

给定两个整数 maxChoosableInteger (整数池中可选择的最大数)和 desiredTotal(累计和),若先出手的玩家是否能稳赢则返回 true ,否则返回 false 。假设两位玩家游戏时都表现 最佳 。

示例 1:

输入:maxChoosableInteger = 10, desiredTotal = 11
输出:false
解释:
无论第一个玩家选择哪个整数,他都会失败。
第一个玩家可以选择从 1 到 10 的整数。
如果第一个玩家选择 1,那么第二个玩家只能选择从 2 到 10 的整数。
第二个玩家可以通过选择整数 10(那么累积和为 11 >= desiredTotal),从而取得胜利.
同样地,第一个玩家选择任意其他整数,第二个玩家都会赢。

示例 2:

输入:maxChoosableInteger = 10, desiredTotal = 0
输出:true

示例 3:

输入:maxChoosableInteger = 10, desiredTotal = 1
输出:true

 

提示:

  • 1 <= maxChoosableInteger <= 20
  • 0 <= desiredTotal <= 300

2.思路

这道题数据范围比较小,可以想到是状态压缩的情况,但是状态十分复杂,我是参考题解想的。一个数拿回不能放回,即只能使用一次,因此需要使用一个数据结构记录状态,C++和Java都可以使用Map作为记录。状态就是当前这个数有没有使用,使用的话这一位就为1;如100是3。第i位为1表示i被使用。

如果是先手必输的话 应该是 所有情况都是后手必胜;如果是先手必胜的话 是存在一种情况是后手必输

3.代码

class Solution {
public:
    bool canIWin(int maxChoosableInteger, int desiredTotal) {
       if(((1+maxChoosableInteger)*maxChoosableInteger*0.5)<desiredTotal)
            return false;
        return dfs(maxChoosableInteger,0,desiredTotal,0);
    }
    bool dfs(int maxChoosableInteger, int userNumbers, int desiredTotal, int currentTotals)
    {
        if(memory.count(userNumbers)==0)
        {
            bool res=false;
            for(int i=0;i<maxChoosableInteger;i++)
            {
                int temp=((userNumbers>>i)&1);
                if( temp==0)
                {
                    int sum=i+1+currentTotals;
                    if(sum>=desiredTotal)
                    {
                        res=true;
                        break;
                    }
                    //判断对方是否输
                    int x=userNumbers |(1<<i);
                    int total=currentTotals+i+1;
                    if(!dfs(maxChoosableInteger,x,desiredTotal,total))
                    {
                        res=true;
                        break;
                    }
                }
            }
            memory.insert({userNumbers,res});
        }
        return memory.find(userNumbers)->second;
    }
     map<int,bool> memory;
};

 

posted @ 2022-11-17 16:40  追·不逝  阅读(43)  评论(0编辑  收藏  举报