JAVA程序设计:我能赢吗(LeetCode:464)

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

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

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

给定一个整数 maxChoosableInteger (整数池中可选择的最大数)和另一个整数 desiredTotal(累计和),判断先出手的玩家是否能稳赢(假设两位玩家游戏时都表现最佳)?

你可以假设 maxChoosableInteger 不会大于 20, desiredTotal 不会大于 300。

示例:

输入:
maxChoosableInteger = 10
desiredTotal = 11

输出:
false

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

思路:好久没做博弈论题了,也算是重新回顾了一下,按照题目描述,两个玩家极度聪明,因此,他们的每一步都是朝着必赢态去的,换句话说,我们枚举当前玩家能拿的所有情况,若存在至少一种方法使得当前玩家能赢,则该玩家必赢!因此我们所要做的工作就是每次枚举当前玩家所能执行的操作,尽量的找到他能够赢的方法即可。

好歹只有20这么大,我们可以直接爆搜,然后拿记忆化搜索优化一下,同时一个数的二进制表示不超过20位,我们可以按位存储哪一个数字是已经拿过的。

class Solution {
    public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
        
    	if(maxChoosableInteger>=desiredTotal)
        	return true;
        
        int maxSumCanReach=(maxChoosableInteger)*(maxChoosableInteger+1)/2;
        
        if(maxSumCanReach map=new HashMap<>();
        
        return dfs(0,maxChoosableInteger,desiredTotal,map);
    }
    
    private boolean dfs(int now,int maxChoosableInteger,int desiredTotal,Mapmap) {
    	
    	if(map.containsKey(now)) return map.get(now);
    	
    	boolean flag=false;
    	for(int num=maxChoosableInteger;num>=1;num--) {
    		if(jud(now,num)) continue;
    		if(num>=desiredTotal)
    			flag=true;
    		else {
    			int usednum=now | (1<>num) & 1) == 1;
    }
}

 

你可能感兴趣的:(JAVA程序设计:我能赢吗(LeetCode:464))