首页 > 其他分享 >动态规划的“三步走”方法

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

时间:2024-07-13 16:56:39浏览次数:13  
标签:11 状态 01 int 三步走 动态 规划 dp define

“三步走”方法

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

  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;
}

标签:11,状态,01,int,三步走,动态,规划,dp,define
From: https://www.cnblogs.com/catting123/p/18300336

相关文章

  • 洛谷 P2478 [SDOI2010] 城市规划 题解
    题意简述仙人掌上求至少间隔两个位置的最大独立集。(仙人掌指,没有一条边在两个或以上的环里的无向图。)题目分析仙人掌就是树套环,即树上每个结点都是一个结点或环。那么将题目拆解成树上DP和环上DP即可。用tarjan缩点即可。树上DP先来看看树上DP。显然每个点有三个状......
  • 动态规划中01背包问题
    动态规划中01背包问题:这记录一下自己的思考和总结:详细讲解:添加链接描述这种题目中有两种解题方法一是二维数组dp[i][j]表示0-i区间背包容量为j的最大价值那么可以有两个方向推出来dp[i][j],不放物品i:由dp[i-1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][......
  • 【国内超大型智能算力中心建设白皮书 2024】_智算中心算力规划
    文末有福利!智算中心建设通过领先的体系架构设计,以算力基建化为主体、以算法基建化为引领、以服务智件化为依托,以设施绿色化为支撑,从基建、硬件、软件、算法、服务等全环节开展关键技术落地与应用。一、体系架构(一)总体架构图8智算中心总体架构智能算力中心建设白皮书,......
  • 暑假大学编程的规划及目标
    我是一名即将步入大二的一名学生,在读一所全日制专科。虽然高考并没有考好,但是这并不妨碍我继续前进。下面就是我的暑假大学编程职业规划,希望对你有帮助。暑假在家太无聊了,闲着也是闲着,我打算把C语言的基础好好的打牢固。我们可以在哔哩哔哩上面找相应的内容,例如:鹏哥的C语言......
  • 动态条件实现java
    提交页面设计 json数据格式[{"name":"规则1","action":{"with":[{"type":"SHOW","targets":[......
  • mybatis动态Sql(where)和sql片段
    sql片段的定义;1<sqlid="condition">2<iftest="entity.dicttype!=null">and`dicttype`=#{entity.dicttype}</if>3<iftest="entity.dictname!=nullandentity.dictname!=''......
  • 动态添加HTML时onclick函数参数传递
    onclick函数动态传参1.参数为数值类型时:var tmp=123;var strHTML="<divonclick=func(" +tmp+")>点击弹出数据及其类型</div>";info.append(strHTML); function func(tmp){    alert(typeof tmp+"" +tmp);}string12......
  • jdk动态代理与cglib动态代理
    最近在用java实现redis,在使用动态代理时遇到了一点问题,即使用jdk动态代理(Invocationhandler)时,如果代理对象是一个接口的实现类,那么此时动态代理获取到的method对象是接口中的,而不是实现类的,现象是:我在实现类中对接口方法上新增了注解,但是此刻method反射获取不到注解信息,于是大概......
  • Vue遇到MathJax渲染的数学公式在翻页后仍然停留或无法动态加载
    Vue遇到MathJax渲染的数学公式在翻页后仍然停留或无法动态加载在使用Vue.js时,遇到MathJax渲染的数学公式在翻页后仍然停留的问题,通常是因为Vue的单页面应用(SPA)特性导致的DOM更新问题。MathJax通常在页面加载时渲染数学公式,但在SPA中,页面切换时可能不会重新渲染MathJax,导致......
  • 易优cms网站user功能:动态显示购物车、登录、注册、退出、会员中心的入口-Eyoucms
    user登录注册入口标签 [基础用法]名称:user功能:动态显示购物车、登录、注册、退出、会员中心的入口;语法:  {eyou:usertype='userinfo'}    <divid="{$field.htmlid}">       <ahref="{$field.loginurl}">登录</a>       <ahref="{$fi......