464. 我能赢吗

原题链接:

464. 我能赢吗

https://leetcode.cn/problems/can-i-win/description/

完成情况:

在这里插入图片描述

解题思路:

这段代码是一个使用深度优先搜索(DFS)和记忆化搜索(Memoization)的算法,用于解决一个游戏问题。下面是代码的解释:

  1. canIWin 方法:这个方法用于判断玩家是否能赢得游戏。首先,它会检查是否所有可选整数之和小于期望的总数,如果是,则返回 false,否则调用 dfs 方法。

  2. dfs 方法:这个方法是深度优先搜索的核心。它会递归地尝试所有可能的选择,记录已经使用过的数字,并在适当的时候进行回溯。具体步骤如下:

    • 如果当前的选择已经被记录在 memo 中,则直接返回 memo 中对应的结果。
    • 否则,遍历所有可选整数,检查是否该整数已经被使用过。
    • 如果该整数未被使用,判断选择该整数后是否能达到或超过期望的总数,如果是,则返回 true。
    • 否则,递归调用 dfs 方法,更新已使用数字的状态,并继续搜索下一个选择。
    • 最后,将当前选择的结果存入 memo 中,并返回该结果。

这段代码的目的是找出在给定规则下,玩家是否能赢得游戏。通过记忆化搜索,避免重复计算,提高了算法的效率。

参考代码:

_464我能赢吗_记忆化dp

package leetcode板块;

import java.util.HashMap;
import java.util.Map;

public class _464我能赢吗_记忆化dp {
    Map<Integer,Boolean> memoery = new HashMap<Integer,Boolean>();
    /**
     *
     * @param maxChoosableInteger
     * @param desiredTotal
     * @return
     */
    public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
        //  两名玩家轮流 -> 选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和 达到或超过  100 的玩家,即为胜者。
        //  如果我们将游戏规则改为 【“玩家 不能 重复使用整数”】 呢?
        /*
        两个整数 maxChoosableInteger (整数池中可选择的最大数)和 desiredTotal(累计和),
        若先出手的玩家能稳赢则返回 true ,否则返回 false 。假设两位玩家游戏时都表现 最佳 。
        允许选择使用重复的数   -->  先手是否一定能赢?
         */
        if ((1 + maxChoosableInteger) * (maxChoosableInteger) / 2 < desiredTotal){  //如果这些数的累计和的一半不超过目标值,那么永远不可能满足需求
            return false;
        }
        return dfs_canIWin(maxChoosableInteger,0,desiredTotal,0);
    }

    /**
     * 见名知意
     * @param maxChoosableInteger
     * @param usedNumbers
     * @param desiredTotal
     * @param currentTotals
     * @return
     */
    private boolean dfs_canIWin(int maxChoosableInteger, int usedNumbers, int desiredTotal, int currentTotals) {
        if (!memoery.containsKey(usedNumbers)){
            boolean result = false;
            for (int i = 0;i<maxChoosableInteger;i++){  //在这些数中每次都选取最大的数?
                if (((usedNumbers >> i) & 1) == 0){  //从低位到高位开始取值
                    if (i + 1 + currentTotals >= desiredTotal){
                        result = true;
                        break;
                    }
                    if (!dfs_canIWin(maxChoosableInteger, usedNumbers | (1 << i), desiredTotal, currentTotals+i+1)){
                        result = true;
                        break;
                    }
                }
            }
            memoery.put(usedNumbers,result);
        }
        return memoery.get(usedNumbers);
    }
}

错误经验吸取

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值