动态规划-硬币排成线

news/2024/11/8 14:39:58/

动态规划-硬币排成线

  • 1 描述
  • 2 样例
    • 2.1 样例 1:
    • 2.2 样例 2:
    • 2.3 样例 3:
  • 3 算法解题思路及实现
    • 3.1 算法解题分析
      • 3.1.1 确定状态
      • 3.1.2 转移方程
      • 3.1.3 初始条件和边界情况
      • 3.1.4 计算顺序
    • 3.2 算法实现
      • 3.2.1 动态规划常规实现
      • 3.2.2 动态规划滚动数组

该题是lintcode的第394题, https://www.lintcode.com/problem/394/,解题思路参考九章侯老师给的建议。

1 描述

有 n 个硬币排成一条线。两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止。拿到最后一枚硬币的人获胜。

请判定 先手玩家 必胜还是必败?

若必胜, 返回 true, 否则返回 false.

Lintcode超级VIP年卡 618预售 享买一年送一年

微信加【jiuzhang1104】备注【VIP】即可参加

2 样例

2.1 样例 1:

输入: 1
输出: true

2.2 样例 2:

输入: 4
输出: true
解释:
先手玩家第一轮拿走一个硬币, 此时还剩三个.
这时无论后手玩家拿一个还是两个, 下一次先手玩家都可以把剩下的硬币拿完.

2.3 样例 3:

输入: 5
输出: true
解释:
先手玩家第一轮拿走两枚硬币, 此时还剩三个.
这时无论后手玩家拿一个还是两个, 下一次先手玩家都可以把剩下的硬币拿完.

3 算法解题思路及实现

3.1 算法解题分析

3.1.1 确定状态

这是一个博弈型动态规划类算法题,这中类型的算法解题分析不是从最后一步分析,而是从第一步分析,原因是随着硬币的减少,问题越来越简单。
假设两名选手分别为A和B,A为硬币为N时的先手,而当A拿走一或则两枚硬币之后,B则成为剩余硬币的先手,因此A要保证在自己拿走1或者2枚硬币的时候至少有一种情况是可以赢的。
子问题就转换为:
面对N枚硬币,A作为先手是不是必胜,
则需要知道面对N - 1和N - 2枚硬币B作为先手是不是必胜,
状态:设f[i]表示面对i个石子,是否先手必胜f[i] = True/False

3.1.2 转移方程

状态:设f[i]表示面对i个石子,是否先手必胜f[i] = True/False
在这里插入图片描述

f[i] = (f[i-1] == FALSE OR f[i-2] == FALSE)

3.1.3 初始条件和边界情况

  • 设f[i]表示面对i个石子,是否先手必胜f[i] = True/False
  • f[i] = (f[i-1] == FALSE OR f[i-2] == FALSE)
  • f[0] = FALSE 面对0枚硬币,先手必败
  • f[1] = f[2] = True, 面对1枚或2枚硬币,先手必胜

3.1.4 计算顺序

  • f[0], f[1], f[2], …, f[N]
  • 如果f[N] = true,则先手必胜,否则先手必败
  • 时间负责度为O(N)
  • 空间复杂度为:O(N)

3.2 算法实现

3.2.1 动态规划常规实现

public class Solution {/*** @param n: An integer* @return: A boolean which equals to true if the first player will win*/public boolean firstWillWin(int n) {// write your code hereif (n <= 0) {return false;}if (n <= 2) {return true;}boolean [] f = new boolean[n + 1];f[0] = false;f[1] = true;for (int i = 2; i <= n; i++) {f[i] = (!f[i - 1] || !f[i - 2]);}return f[n];}
}

3.2.2 动态规划滚动数组

public class Solution {/*** @param n: An integer* @return: A boolean which equals to true if the first player will win*/public boolean firstWillWin(int n) {// write your code hereif (n <= 0) {return false;}if (n <= 2) {return true;}boolean [] f = new boolean[2];f[0] = false;f[1] = true;for (int i = 2; i <= n; i++) {f[i % 2] = !(f[(i -1) % 2] && f[(i - 2) % 2]);}return f[n % 2];}
}

http://www.ppmy.cn/news/142399.html

相关文章

python-pandas按各种时间统计

使用到的库 pandas、matplotlib、numpy 使用到的函数 df.resample(“H”).sum() 参数 B business day frequency C custom business day frequency (experimental) D calendar day frequency W weekly frequency M month end frequency BM business month end frequency CBM…

内核 panic

/* * 2023/5/31 11:45 qing 38度 */ /* * Unable to handle kernel NULL pointer dereference at virtual address 00000000 */ 非法地址访问出错,使用了空指针 /* * BUG: scheduling while atomic: fpv_cams/605/0x00010001 */ 试图在不应该休眠的地…

国产给力啊啊啊----国产MCU-CW32F030开发学习

国产MCU-CW32F030开发学习 1. 相关资料下载 1.1 武汉芯源半导体 武汉芯源半导体官网 武汉芯源半导体 武汉芯源 21ic 电子论坛 21ic 电子论坛 1.2 CW32F030系列资料 CW32F030技术文档 • 内核&#xff1a;ARM Cortex-M0 – 最高主频64MHz • 工作温度&#xff1a;-40℃ 至…

安卓MVI架构模式常见问题:View层接收不到新的StateFlow状态

1、检查ui层是否正确监听了Flow 如果监听操作封装在ui层的基类&#xff0c;如BaseActivity&#xff0c;的initView方法中&#xff0c;那么实现类在重新父类的initView方法时&#xff0c;必须调用super.initView() 2、检查Ui层当前的ViewModel和发送新ui状态的ViewModel是否是…

uni-app使用echarts绘制数据可视化图

先打开项目 然后选择 使用命令行窗口打开所在目录(U) 在弹出的终端中输入指令来引入依赖 npm install echarts然后 我们 打开echarts的官网 点击这里这个 示例 找一个自己喜欢的案例点进去 我这里就用一个最简单的吧 代码看着不会乱 将他这个 option中的内容复制出来 然后…

Qt 帮助项目

Qt帮助项目收集生成压缩帮助文件所需的所有数据。除了诸如目录&#xff0c;索引关键字和帮助文档之类的实际帮助数据外&#xff0c;它还包含一些其他信息&#xff0c;例如用于标识帮助文件的名称空间。一个帮助项目代表一个文档集。 Qt帮助项目文件格式 文件格式是基于XML的。…

Error running Android Debugger (8600): Unable to open debugger port (localhost:8600): java.net.Conne

adb kill-server adb start-server 在AS底部找到Terminal 命令输入框&#xff0c;依次输入上面两个命令

z370完美黑苹果_完工!搞掂i5-8600K 华硕PRIME Z370-P GTX 1060黑苹果安装

鲁大师配置图CPU&#xff1a;i5-8600K&#xff0c;主板&#xff1a;华硕PRIME Z370-P&#xff0c;内存&#xff1a;16GB&#xff0c;主硬盘&#xff1a;三星SSD 750EVO 250GB,显卡&#xff1a;GTX 1060 6GB技嘉&#xff0c;声卡&#xff1a;ALC887&#xff0c;网卡&#xff1a;…