【2024.1.30练习】李白打酒加强版(25分)

2024-01-30 22:44

本文主要是介绍【2024.1.30练习】李白打酒加强版(25分),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述


题目思路

在最多数据的情况下,有100个店100朵花,总情况为C_{200}^{100}的天文数字,暴力枚举已经不可能实现,考虑使用动态规划解决问题。最后遇到的一定是花,所以思路更倾向于倒推。

建立二维数组dp[i][j],容易联想到i为经过的花数,j为经过的店数,dp[i][j]的值代表此时酒量。但是这样i , j不能确定唯一的dp[i][j]。且酒壶中的酒量最大可能达到2^{100}数量级,如何储存这个大数据也是问题。

再关注数学问题本身。设第i次遇到店添加的酒量为A_{i},易得:

2+\sum_{1}^{N}A_i=M \leftrightharpoons A_1+A_2+A_3+...+A_N=M-2

根据题意,壶中酒量最大也不会超过100斗,极大简化了数据量。

此外由数据范围可以得到M<=2或N-M>7时无解,可以拿到极端测试点的分数。

在设计状态困难的情况下先找递推关系,写几组排列组合可以得到:

A(i,j)i个店j朵花的排列组合总数,则A(i,j) = A(i-1,j)+A(i,j-1)

这样可以得到有关店数和花数的状态转移方程,然而这道题还与壶中酒量这一额外变量有关,因此考虑用三维数组存储数据。设计三维数组dp[i][j][k]dp[i][j][k]的值代表为经过i个店,j朵花时壶中的酒量为k的方案数。初始状态显然为:

dp[0][0][k]=\begin{cases} & 1\text{ (k =2) } \\ & 0\text{ (k!=2) } \end{cases}
dp[1][0][k]=\begin{cases} & 1\text{ (k =4) } \\ & 0\text{ (k!=4) } \end{cases}

dp[0][1][k]=\begin{cases} & 1\text{ (k =1) } \\ & 0\text{ (k!=1) } \end{cases}

实际上后两个式子都能被递推出来,是多余的。接下来建立状态转移方程:

dp[i][j][k]=dp[i-1][j][\tfrac{k}{2}]+dp[i][j-1][k+1] \ \ \ (\tfrac{k}{2}\in \mathbb{Z}) 

dp[i][j][k]=dp[i][j-1][k+1] \ \ \ (\tfrac{k}{2}\notin \mathbb{Z}) 

第二个式子省略了最后遇到的是店的情况,因为此时酒量为奇数,不可能遇到店。但是用上面的状态转移方程可能会出现i-1j-1为负值的情况,因此完整的状态转移方程如下:

dp[i][j][k]=dp[i-1][j][\tfrac{k}{2}]+dp[i][j-1][k+1] \ \ \ (\tfrac{k}{2}\in \mathbb{Z}\bigcap_{}^{}i-1,j-1\in \mathbb{N})

dp[i][j][k]=dp[i][j-1][k+1] \ \ \ (\tfrac{k}{2}\notin \mathbb{Z}\bigcup i-1\notin \mathbb{N})

dp[i][j][k]=dp[i-1][j][\tfrac{k}{2}] \ \ \ (\tfrac{k}{2}\in \mathbb{Z}\bigcap_{}^{} j-1\notin \mathbb{N})

最终剩下的是一朵花和一斗酒。因此我们递推完成后,只需查看dp[N][M-1][1]的值,即可获取答案。


我的代码

#include <iostream>
#include <algorithm>
using namespace std;
int dp[101][101][101];
int main() {int n;int m;cin >> n >> m;//设置初始状态int i;int j;int k;for (i = 0; i < 101; i++){if (i == 2) {dp[0][0][i] = 1;}else {dp[0][0][i] = 0;}}//动态规划for (i = 0; i <= n; i++){for (j = 0; j <= m; j++){for ( k = 0; k <= 100; k++){//分类讨论if (k % 2 == 0 && i >= 1 && j >= 1) {dp[i][j][k] = (dp[i - 1][j][k / 2] + dp[i][j - 1][k + 1])% 1000000007;}else if ((k % 2 != 0 || i <= 1) && j >= 1) {dp[i][j][k] = (dp[i][j - 1][k + 1]) % 1000000007;}else if (k % 2 == 0 && j <= 1 && i >= 1) {dp[i][j][k] = (dp[i - 1][j][k / 2]) % 1000000007;}}}}//获取答案int ans = dp[n][m - 1][1];cout << ans;return 0;
}

记得数据可能过大,每次运算都要取模。

这篇关于【2024.1.30练习】李白打酒加强版(25分)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/661781

相关文章

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作

2024网安周今日开幕,亚信安全亮相30城

2024年国家网络安全宣传周今天在广州拉开帷幕。今年网安周继续以“网络安全为人民,网络安全靠人民”为主题。2024年国家网络安全宣传周涵盖了1场开幕式、1场高峰论坛、5个重要活动、15场分论坛/座谈会/闭门会、6个主题日活动和网络安全“六进”活动。亚信安全出席2024年国家网络安全宣传周开幕式和主论坛,并将通过线下宣讲、创意科普、成果展示等多种形式,让广大民众看得懂、记得住安全知识,同时还

RabbitMQ练习(AMQP 0-9-1 Overview)

1、What is AMQP 0-9-1 AMQP 0-9-1(高级消息队列协议)是一种网络协议,它允许遵从该协议的客户端(Publisher或者Consumer)应用程序与遵从该协议的消息中间件代理(Broker,如RabbitMQ)进行通信。 AMQP 0-9-1模型的核心概念包括消息发布者(producers/publisher)、消息(messages)、交换机(exchanges)、

【Rust练习】12.枚举

练习题来自:https://practice-zh.course.rs/compound-types/enum.html 1 // 修复错误enum Number {Zero,One,Two,}enum Number1 {Zero = 0,One,Two,}// C语言风格的枚举定义enum Number2 {Zero = 0.0,One = 1.0,Two = 2.0,}fn m

MySql 事务练习

事务(transaction) -- 事务 transaction-- 事务是一组操作的集合,是一个不可分割的工作单位,事务会将所有的操作作为一个整体一起向系统提交或撤销请求-- 事务的操作要么同时成功,要么同时失败-- MySql的事务默认是自动提交的,当执行一个DML语句,MySql会立即自动隐式提交事务-- 常见案例:银行转账-- 逻辑:A给B转账1000:1.查询

html css jquery选项卡 代码练习小项目

在学习 html 和 css jquery 结合使用的时候 做好是能尝试做一些简单的小功能,来提高自己的 逻辑能力,熟悉代码的编写语法 下面分享一段代码 使用html css jquery选项卡 代码练习 <div class="box"><dl class="tab"><dd class="active">手机</dd><dd>家电</dd><dd>服装</dd><dd>数码</dd><dd

【JavaScript】LeetCode:21-25

文章目录 21 最大子数组和22 合并区间23 轮转数组24 除自身以外数组的乘积25 缺失的第一个正数 21 最大子数组和 贪心 / 动态规划贪心:连续和(count)< 0时,放弃当前起点的连续和,将下一个数作为新起点,这里提供使用贪心算法解决本题的代码。动态规划:dp[i]:以nums[i]为结尾的最长连续子序列(子数组)和。 dp[i] = max(dp[i - 1]

014.Python爬虫系列_解析练习

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈 优

如何快速练习键盘盲打

盲打是指在不看键盘的情况下进行打字,这样可以显著提高打字速度和效率。以下是一些练习盲打的方法: 熟悉键盘布局:首先,你需要熟悉键盘上的字母和符号的位置。可以通过键盘图或者键盘贴纸来帮助记忆。 使用在线打字练习工具:有许多在线的打字练习网站,如Typing.com、10FastFingers等,它们提供了不同难度的练习和测试。 练习基本键位:先从学习手指放在键盘上的“家位”开始,通常是左手的

c++习题30-求10000以内N的阶乘

目录 一,题目  二,思路 三,代码    一,题目  描述 求10000以内n的阶乘。 输入描述 只有一行输入,整数n(0≤n≤10000)。 输出描述 一行,即n!的值。 用例输入 1  4 用例输出 1  24   二,思路 n    n!           0    1 1    1*1=1 2    1*2=2 3    2*3=6 4