动态规划的“三步走”方法

news/2024/11/15 20:00:49/文章来源:https://www.cnblogs.com/catting123/p/18300336

“三步走”方法

动态规划问题种类较多,但大多都能通过“三步走”方法解决。

  1. 状态表示:将具体问题抽象为数学问题,明确需要表示的状态,数组中的下标分别表示哪种状态。
  2. 状态转移:状态转移相当于递推公式。主要有两种方式,可以从上一个状态转移到当前状态,或者从当前状态转移到下一个状态。可根据具体问题确定使用哪一种方式更方便。
  3. 边界条件:需要确定状态转移的初始条件,以及循环的边界,最后需要清楚答案存储的变量是哪一个。

举例说明:旅行2024

下面以一个线性dp的题目说明“三步走”方法如何使用。

题目描述
你面前有一张地图,其形状为一个由2行n列组成的网格。地图上的每一段道路都可能位于阳光下(白色)或阴影中(黑色)。
两个部分被认为是相连的,如果它们直接相邻并处于相同的状态(要么都是在阳光下,要么都是在阴影中)。一个图案被定义为一组具有相同状态的相连部分。
你的任务寻找有多少为地图的着色方案使得其恰好有 \(k\) 种不同的图案。

输入描述
唯一的一行包含两个整数 \(n\)\(k\),分别代表地图网格中的列数和所需的不同景观或图案的数量。约束条件是 \(1 \le n \le 1000\)\(1 \le k \le 2n\)

输出描述
输出恰好经历 \(k\) 种景观或图案的方式数量,结果对 \(1000000007\) 取模。

样例输入

3 4

样例输出

12

样例解释
其中一种符合条件的方案如图所示:

样例输入

1 2

样例输出

2

下面进行三步走分析:

  1. 状态表示:用 \(dp\) 数组表示状态,\(dp[i][u][j]\)\(i\) 表示 \(n\) 列中的第 \(i\) 列,\(u\) 表示哪一种状态(共有 \(4\) 种状态),\(j\) 表示当前已经表示了 \(k\) 种图案中的 \(j\) 种。
  2. 状态转移:当前状态只与上一时刻状态有关,所以需要知道上一列状态和当前列状态进行状态转移。上一时刻状态转移到当前状态变化的方案数可能有三种,+0+1+2。下面第一列表示上一列状态,第二列表示当前列状态,共有 \(4\times4=16\) 种状态。
    (1) 先讨论最简单的+2的情况,共有两种可能:
    10  01
    01  10
    
    可用((u ^ v == 3) && abs(u - v == 1))判断。
    (2) 然后讨论相对简单的+0的情况:
    00  11  00  11    00  10  01  11
    00  00  11  11    10  00  11  01
    
    可用else if((u ^ v == 0) || u == 1 || u == 2)判断,此处能用后两个判断条件也是因为写了else if而不是直接用if
    (3) 最后else直接得出相对较复杂的+1的情况,无需判断。下面也列出了所有+1的情况:
    01  10    00  01  10  11
    01  10    01  00  11  10
    
  3. 边界条件:由于 \(i\)\(i-1\) 转移而来,所以需要提前设置 \(i=1\) 时的方案数,\(i\) 只需从 \(2\) 循环到 \(n\) 即可,\(j\) 需要从 \(1\) 循环到 \(k\),上一时刻和当前时刻都需循环 \(4\) 种状态。由于随着 \(i\) 的增大,\(j\) 不会减小,所以最终的答案在 \(\sum_{u=0}^{3}dp[n][u][k]\) 中,在计算时需要取模。

根据以上分析编写代码如下:

#include <bits/stdc++.h>
#define int long long
#define forn(i, a, b) for (int i = a; i < b; i++)
#define fore(i, a, b) for (int i = a; i <= b; i++)
#define rfon(i, a, b) for (int i = a; i > b; i--)
#define rfoe(i, a, b) for (int i = a; i >= b; i--)
#define vb v.begin()
#define ve v.end()
#define vc v.clear()
#define vs (int)v.size()
#define ss (int)s.size()
#define sb s.back()
#define rs(i) resize(i)
#define ft first
#define sd second
#define P pair<int, int>
#define inf 0x3f3f3f3f
#define Ios ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
const int mod = 1e9 + 7;int dp[1005][4][2005];void solve() {int n, k;cin >> n >> k;dp[1][0][1] = dp[1][1][2] = dp[1][2][2] = dp[1][3][1] = 1;for (int i = 2; i <= n; i++) {for (int j = 1; j <= k; j++) {for (int u = 0; u < 4; u++) {for (int v = 0; v < 4; v++) {if ((u ^ v == 3) && abs(u - v == 1)) {dp[i][v][j + 2] = (dp[i][v][j + 2] + dp[i - 1][u][j]) % mod;} else if ((u ^ v == 0) || u == 1 || u == 2) {dp[i][v][j] = (dp[i][v][j] + dp[i - 1][u][j]) % mod;} else {dp[i][v][j + 1] = (dp[i][v][j + 1] + dp[i - 1][u][j]) % mod;}}}}}int ans = 0;for (int i = 0; i < 4; i++) {ans = (ans + dp[n][i][k]) % mod;}cout << ans << "\n";
}signed main() {Ios;solve();return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

N1盒子挂载磁盘-解决盒子重启后无法自动挂载问题

Markdown Example.centered-text { text-align: center; font-size: 40px; font-family: "Times New Roman", Georgia, serif }N1盒子挂载磁盘挂载步骤: step 1step 2如果提示挂载已存在、就先卸载挂载分区step 3 回到首页重新挂载step 4此时已经挂载成功、但是默认…

记一次 CDN 流量被盗刷经历

先说损失,被刷了 70 多RMB,600多G流量,PCDN 真可恶啊,这里分享一下过程和止损手段。先说损失,被刷了 70 多RMB,还好止损相对即时了,亏得不算多,PCDN 真可恶啊。600多G流量,100多万次请求。 怎么发现的 先是看到鱼皮大佬发了一篇推文突发,众多网站流量被盗刷!我特么也…

爬虫初识

一 介绍 二 安装 三 基本使用 四 选择器 五 等待元素被加载 六 元素交互操作 七 其他 八 项目练习_____egon新书python全套来袭:https://egonlin.com/book.html一 介绍selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题…

手动更新补丁添加到 Win10 ISO映像包

手动更新补丁添加到 Win10 ISO映像包手动更新补丁添加到 Win10 ISO映像包操作步骤 下载原版ISO镜像文件并解压到指定文件夹中备用从 Microsoft 更新目录下载更新补丁只需要下载最新的累计更新即可,然后放入单独的文件中备用确定版本 Dism /Get-ImageInfo /ImageFile:D:\SW_DVD…

[HNCTF 2022 WEEK2]ez_SSTI

[HNCTF 2022 WEEK2]ez_SSTIpayload:?name={{.__class__.__base__.__subclasses__()[137].__init__.__globals__[__builtins__][eval](__import__("os").popen("cat flag").read())}}1.首先输入{{8*8}}判断漏洞类型2.然后输入{{.__class__}}判断当前对象所…

【操作系统原理】第六章课后习题

前言课本: 操作系统原理(第五版)[费翔林,骆斌编著] 习题: 主要习题内容是第一章到第六章,具体内容如下表章节 内容 链接第一章 思考题1,3,7、应用题7,12(1)~(4) https://blog.csdn.net/Zchengjisihan/article/details/136493304?spm=1001.2014.3001.5501第二章 思考题…

【操作系统原理】第一章课后习题

前言课本: 操作系统原理(第五版)[费翔林,骆斌编著] 习题: 主要习题内容是第一章到第六章,具体内容如下表章节 内容 链接第一章 思考题1,3,7、应用题7,12(1)~(4) https://blog.csdn.net/Zchengjisihan/article/details/136493304?spm=1001.2014.3001.5501第二章 思考题…

【操作系统原理】第二章课后习题

前言课本: 操作系统原理(第五版)[费翔林,骆斌编著] 习题: 主要习题内容是第一章到第六章,具体内容如下表章节 内容 链接第一章 思考题1,3,7、应用题7,12(1)~(4) https://blog.csdn.net/Zchengjisihan/article/details/136493304?spm=1001.2014.3001.5501第二章 思考题…

【操作系统原理】第三章课后习题

前言课本: 操作系统原理(第五版)[费翔林,骆斌编著] 习题: 主要习题内容是第一章到第六章,具体内容如下表章节 内容 链接第一章 思考题1,3,7、应用题7,12(1)~(4) https://blog.csdn.net/Zchengjisihan/article/details/136493304?spm=1001.2014.3001.5501第二章 思考题…

8、Oracle中的创建和管理表

最近项目要用到Oracle,奈何之前没有使用过,所以在B站上面找了一个学习视频,用于记录学习过程以及自己的思考。 视频链接: 【尚硅谷】Oracle数据库全套教程,oracle从安装到实战应用 如果有侵权,请联系删除,谢谢。学习目标:描述主要的数据库对象 创建表 描述各种数据类型…

ubuntu 快速回到桌面

如下设置快捷键为 Super + D,

TCP三次握手的意外情况分析

> 其实很简单,就像我个人给别人发信息一样,有个重传机制,毕竟对方可能突然有事忘看了,或者说看完了忘了回,所以我本人会重传,那么接下来就以聊天的角度来给大家解析一下TCP三次握手时的意外情况以及应对方针注文中的大部分知识非我原创,我只是知识的搬运工,并且尝试搬运进脑…