LeetCode·每日一题·1223.掷骰子模拟·记忆化搜索

news2024/11/25 22:30:27

作者:小迅

链接:https://leetcode.cn/problems/dice-roll-simulation/solutions/2103471/ji-yi-hua-sou-suo-zhu-shi-chao-ji-xiang-xlfcs/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

题目

示例

思路

题意 -> 给定一个字符串规定相同类型的骰子连续出现的最大值,返回投掷 n 次后能出现的 骰数 的不同序列个数

题目说是 骰子模拟,那么直接按照题目意思进行模拟呢?

想一想,掷了一个骰子(设值为 x)后,会发生什么情况?

既然题目有 rollMax 的限制,那么分类讨论:

  • 如果和上一个骰子值相同,那么 x 的连续出现次数不能超过 rollMax[x];

  • 如果不同,那么可以重置连续出现次数为 1。

关键词提取:「上一个骰子值」「连续出现次数」

那么在回溯中就需要知道(为了方便后面转成递推,定义成剩余):

  • 剩余掷骰子的次数,用 i 表示;

  • 上一个骰子值,用 last 表示;

  • last 的剩余连续出现次数,用 left 表示。

这样就确定了递归的参数,递归的返回值就是骰子序列个数。

要递归到哪里去呢?我们可以用回溯中的经典技巧「枚举选哪个」:

  • 如果选的骰子值和上一个相同,且 left>0,那么递归到 (i−1,last,left−1);

  • 如果不同,设为 j,那么递归到 (i−1,j,rollMax[j]−1)。

枚举 j=0,1,2,3,4,5,把递归后的结果相加,就是当前 (i,last,left) 的答案。

递归到 n=0 时结束,返回 1,表示找到了一个合法骰子序列

整个回溯过程是有大量重复递归调用的。由于递归函数没有副作用,无论多少次调用 dfs(i,last,left) 算出来的结果都是一样的,因此可以用记忆化搜索来优化:

  • 如果一个状态(递归入参)是第一次遇到,那么可以在返回前,把状态及其结果记到一个 cache 数组(或者哈希表)中;

  • 如果一个状态不是第一次遇到,那么直接返回 cache 中保存的结果。

cache[n][x][y] - n 表示 当前剩余投掷次数, x 表示上一次投掷骰子值, y表示 上一次投掷骰子值 剩余的出现次数;

为啥可以到达记忆化效果,因为当前投掷结果的有效性只和上一次的投掷结果相关,「先掷 1 后掷 3」和「先掷 2 后掷 3」,都会递归到 dfs(n−2,3,rollMax[3]−1)。

如何转动态规划 :

  • 可以去掉递归中的「递」,只保留「归」的部分,即自底向上计算。

做法:

  • dfs 改成 f 数组;

  • 递归改成循环(每个参数都对应一层循环);

  • 递归边界改成 f 数组的初始值。

代码注释超级详细

代码

const long MOD = 1e9 + 7;

int dfs(int i, int last, int *rollMax, int left, int (*cache)[6][15])
{
    if (i == 0) return 1;
    int *c = (int *)&(cache[i][last][left]);
    if (*c >= 0) return *c;//如果之前算过就不需要重新计算
    long res = 0;
    for (int j = 0; j < 6; ++j)
        if (j != last) res += dfs(i - 1, j, rollMax, rollMax[j] - 1, cache);
        else if (left) res += dfs(i - 1, j, rollMax, left - 1, cache);
    return *c = res % MOD;
}


int dieSimulator(int n, int* rollMax, int rollMaxSize){
    int cache[n][6][15];//记忆化数组
    memset(cache, -1, sizeof(cache)); // -1 表示没有访问过
    long ans = 0;
    for (int j = 0; j < 6; ++j)//枚举初始状态0-6
        ans += dfs(n - 1, j, rollMax, rollMax[j] - 1, cache);
    return ans % MOD;
}

作者:小迅
链接:https://leetcode.cn/problems/dice-roll-simulation/solutions/2103471/ji-yi-hua-sou-suo-zhu-shi-chao-ji-xiang-xlfcs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
    const long MOD = 1e9 + 7;
public:
    int dieSimulator(int n, vector<int> &rollMax) {
        int m = rollMax.size(), f[n][m][15];
        for (int j = 0; j < m; ++j)
            for (int k = 0; k < rollMax[j]; ++k)
                f[0][j][k] = 1;
        for (int i = 1; i < n; ++i)
            for (int last = 0; last < m; ++last)
                for (int left = 0; left < rollMax[last]; ++left) {
                    long res = 0;
                    for (int j = 0; j < m; ++j)
                        if (j != last) res += f[i - 1][j][rollMax[j] - 1];
                        else if (left) res += f[i - 1][j][left - 1];
                    f[i][last][left] = res % MOD;
                }
        long ans = 0;
        for (int j = 0; j < m; ++j)
            ans += f[n - 1][j][rollMax[j] - 1];
        return ans % MOD;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/336537.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

libxlsxwriter中文报错问题

libxlsxwriter库在windows系统下VS中存在中文输入报错问题。这在小白关于libxlsxwriter的第一篇博客libxlsxwriter初体验里有所阐述。当时小白给出的解决方案是将文件编码修改成不带签名的utf-8。后来在使用中&#xff0c;小白发现这样并没有完全解决问题。有的中文可以正常写入…

VHDL语言基础-时序逻辑电路-触发器

目录 触发器&#xff1a; D触发器&#xff1a; 触发器的VHDL描述&#xff1a; 触发器的仿真波形如下&#xff1a;​编辑 时钟边沿检测的三种方法&#xff1a; 方法一: 方法二&#xff1a; 方法三&#xff1a; 带有Q非的D触发器&#xff1a; 带有Q非的D触发器的描述&am…

微信小程序 Springboot高校课堂教学管理系统-java

小程序端 学生在小程序端进行注册并且进行登录。 填写自己的个人信息进行注册 登录成功后可以看到有首页、课程资源、测试、互动论坛、我的功能模块。 课程资源学生可以点击想要查看的资源进行观看。 课程分类学生可以按照自己想要的分类进行搜索并且进行观看。 互动论坛可以查…

四种方式的MySQL安装过程 数据库(2)

目录 1. 仓库安装&#xff1a; 1.1 卸载数据库软件&#xff1a; 2. 本地安装&#xff1a; 2.1 卸载数据库软件&#xff1a; 3. 容器安装&#xff1a; 4. 源码安装&#xff1a; 4.1 使用systemctl命令启动进程 1. 仓库安装&#xff1a; &#xff08;1&#xff09;查看版本…

超级详细GitBook和GitLab集成步骤【linux环境】

介绍 本文主要是在 gitlab 上集成 gitbook 实现提交时 gitbook 自动刷新部署 &#xff0c;以及在 linux 环境上搭建 gitlab gitbook,集成 GitLab CI 实现一个企业级或个人的 Wiki 系统 环境准备 1.一台 linux 服务器 2.安装 node 以及 npm 环境 (这里注意 node 环境不要过高 不…

CS反制之批量伪装上线

分析原理&#xff1a; 我们利用Wireshark抓包工具分析一下Cobalt Strike的上线过程是怎么样的 点击木马&#xff0c;主机上线并抓包 查看数据包 可以看到cookie是一串非对称RSA加密类型&#xff0c;需要一个私钥Private Key才能对其进行解密 我们对Cookie解密看看&#xff…

Django框架之系列二

为什么要搭建虚拟环境? 在开发过程中, 当需要使用python的某些工具包/框架时需要联网安装 比如联网安装Django框架django的1.11.11版本 sudo pip install django1.11.11提示&#xff1a;使用如上命令, 会将Django安装到/usr/local/lib/python2.7/dist-packages路径下问题&…

常见的10种网络安全攻击类型

1. DoS 和 DDoS 攻击DoS 是 Denial of Service 的简称&#xff0c;即拒绝服务。单一的 DoS 攻击一般是采用一对一方式的&#xff0c;通过制造并发送大流量无用数据&#xff0c;造成通往被攻击主机的网络拥塞&#xff0c;耗尽其服务资源&#xff0c;致使被攻击主机无法正常和外界…

57 长短期记忆网络(LSTM)【动手学深度学习v2】

57 长短期记忆网络&#xff08;LSTM&#xff09;【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1JU4y1H7PC/?spm_id_fromautoNext&vd_source75dce036dc8244310435eaf03de4e330 长短期记忆网络&#xff08;LSTM&#xff09…

Element UI框架学习篇(四)

Element UI框架学习篇(四) 1 准备工作 1.0 创建Emp表并插入相应数据的sql语句 /*MySQL数据库*/SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for emp -- ---------------------------- DROP TABLE IF EXISTS emp; CRE…

为什么需要内存对齐

内存对齐 为什么需要内存对齐&#xff1f; 平台原因&#xff1a;不是所有的硬件平台都能访问任意内存地址上的任意数据&#xff0c;某些硬件平台只能在某些地址处取某些特定类型的数据&#xff0c;否则抛出硬件异常。为了同一个程序可以在多平台运行&#xff0c;需要内存对齐…

阻塞式队列-生产者消费者模型

1.阻塞队列是什么 阻塞队列是一种特殊的队列. 也遵守 "先进先出" 的原则. 阻塞队列能是一种线程安全的数据结构, 并且具有以下特性: 当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素.当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队…

HLNet代码debug记录

昨天跑HLNet的代码&#xff0c;配环境的时候又双叒叕遇到了一些问题&#xff0c;记录一下&#xff1a; 1.error: identifier “AT_CHECK“ is undefined 出现在python setup.py build develop的时候 参照https://blog.csdn.net/sinat_29957455/article/details/113334944 根据报…

如何在腾讯云服务器上安装Jupyter Notebook示例?

Jupyter简介及服务器端安装 首先&#xff0c;服务器端安装Jupyter。 sudo pip3 install jupyterlab&#xff1a; 启动Jupyter服务 # 设置jupyter web的密码jupyter-notebook password# 创建jupyter工作目录mkdir ~/jupyter_workspace# 启动jupyter (两次ctrlc停止服务)jup…

图解LeetCode——剑指 Offer 32 - III. 从上到下打印二叉树 III

一、题目 请实现一个函数按照之字形顺序打印二叉树&#xff0c;即&#xff1a;第一行按照从左到右的顺序打印&#xff0c;第二层按照从右到左的顺序打印&#xff0c;第三行再按照从左到右的顺序打印&#xff0c;其他行以此类推。 二、示例 2.1> 示例1 提示&#xff1a; …

【软件测试】资深测试工程师说:你真的能做好bug分析吗?

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 bug报告&#xff0c…

Revive:从间谍软件进化成银行木马

2022 年 6 月&#xff0c;Cleafy 研究人员发现了一个新的安卓银行木马 Revive。之所以选择 Revive 这个名称&#xff0c;是因为恶意软件为防止停止工作启用的一项功能名为 revive。 Revive 属于持续潜伏的那一类恶意软件&#xff0c;因为它是为特定目标开发和定制的。这种类型…

Python 四种推导式,包含实例演示

嗨害大家好鸭&#xff01;我是小熊猫~ 这次继续来给大家带来python基础内容~ 源码资料电子书:点击此处跳转文末名片获取 Python 推导式 Python 推导式是一种独特的数据处理方式&#xff0c;可以从一个数据序列构建另一个新的数据序列的结构体。 Python 支持各种数据结构的推…

关于进行vue-cli过程中的解决错误的问题

好久没发文章了&#xff0c;直到今天终于开始更新了&#xff0c;最近想进军全端&#xff0c;准备学习下vue&#xff0c;但是这东西真的太难了&#xff0c;我用了一天的时间来解决在配置中遇到的问题&#xff01;主要问题&#xff1a;cnpm文件夹和vue-cli文件夹的位置不对并且vu…

秒杀项目之网关服务限流熔断降级分布式事务

目录一、网关服务限流熔断降级二、Seata--分布式事务2.1 分布式事务基础2.1.1 事务2.1.2 本地事务2.1.3 分布式事务2.1.4 分布式事务场景2.2 分布式事务解决方案2.2.1 全局事务可靠消息服务2.2.2 最大努力通知2.2.3 TCC事事务三、Seata介绍四、 Seata实现分布式事务控制4.1 案例…