zoukankan      html  css  js  c++  java
  • 动态规划(DP)笔记(三):常见普通题型

    目录

    • 坐标型&双序列型
    • 划分型
    • 状态压缩型

    坐标型&双序列型

    • 特点: 两者都是给的二维输入

      • 双序列型给两个序列

        • 如给定两个字符串序列进行字符匹配:“abc” 与 “abcdefg”,每一个序列对应一个坐标轴:

      • 坐标型给坐标:状态转移对应着表格中坐标的移动

    • 例题

      leetcode 62. 不同路径

      1. 分析

        • 状态表示:使用二维变量 dp[i][j] 表示机器人走到当前位置的路径数
        • 状态转移:机器人自能往右或往下移动,采用被动表示,当前位置的可能路径数为从左侧和上侧的路径数的和 dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
        • 边界:考虑到第一行 dp[0][j] 和第一列 dp[i][0] 只能来自左 / 上侧,故其路径数为 1,即 dp[0][j] = dp[i][0] = 1
      2. 实现

        class Solution {
        public:
            int uniquePaths(int m, int n) {
                int dp[n + 1][m + 1];
                memset(dp, -1, sizeof(dp));
        
                for(int i = 0; i < n; ++i)      //初始化 dp[i][0]
                    dp[i][0] = 1;
        
                for(int j = 1; j < m; ++j)      //初始化 dp[0][j]
                    dp[0][j] = 1;
                
                for(int i = 1; i < n; ++i) {
                    for(int j = 1; j < m; ++j) {
                        dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                    }
                }
        
                return dp[n - 1][m - 1];
            }
        };
        

      leetcode 1143. 最长公共子序列

      1. 分析

        • 状态表示:dp[i][j] 表示 text1 的前 i 位 和 text2 的前 j 位的最大字串长度。

        • 状态转移: 当 text1 的第 i+1 位与 text2 的第 j+1 位相同时,最大子序列长度为前 i、j 的最大子序列长度加1;若不等时,最大子序列长度为前 i+1、j 和前 i、j+1 最大子序列长度的最大值,即:

          [dp[i + 1] [j+1]= egin{cases} dp[i] [j] + 1& ext{text1[i + 1] = text2[j + 1]} \ max(dp[i] [j + 1], dp[i + 1] [j])& ext{text1[i + 1] $ eq$ text2[j + 1]} end{cases} ]

        • 边界:dp[i][0]dp[0][j] 均为 0,表示仅有一个序列时,公共子长度为 0

      2. 实现

        class Solution {
        public:
            int longestCommonSubsequence(string text1, string text2) {
                int row = text1.size(), col = text2.size();
                int dp[row + 1][col + 1];
                memset(dp, 0, sizeof(dp));
        
                for(int i = 1; i <= row; ++i) {
                    for(int j = 1; j <= col; ++j) {
                        if(text1[i - 1] == text2[j - 1])
                            dp[i][j] = dp[i - 1][j - 1] + 1;
                        else
                            dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                    }
                }
                return dp[row][col];
            }
        };
        

    划分型

    • 特点: 将序列不重不漏划分为若干段

    • 思路:

      • 状态:dp[i] 表示考虑了序列前 i 个元素的答案
      • 状态转移:先枚举 dp[i],然后考虑将序列 [i + 1, j] 接在后面自成一段,使其满足条件,然后转移到状态 dp[j]
    • 例题

      [leetcode 132. 分割回文串 II]

      1. 分析: 要求最少的分割次数,相当于分割为最小段数 - 1

        • 状态表示: dp[i] 表示字符串 s 的前 i 个字符分割的最小段数
        • 状态转移:dp[i] = min( dp[j] ) + 1 且 s[j + 1, i] 也是回文段,(j < i)
        • 边界: dp[0] = 0,当前串长为 0,分割的最小段数为 0
      2. 实现

        class Solution {
        public:
            bool checkPalindrome(int l, int r, string s) {     //[l ... r]
                for(int i = l; i <= r; ++i)
                    if(s[i - 1] != s[r + l - i - 1]) return false;
        
                return true;
            }
            
            int minCut(string s) {
                int len = s.size();
                int dp[len + 1];
                memset(dp, -1, sizeof(dp));
                dp[0] = 0;
        
                for(int i = 1; i <= len; ++i) {
                    for(int j = 0; j < i; ++j) {
                        if(dp[j] == -1 || !checkPalindrome(j + 1, i, s))
                            continue;
                        if(dp[i] == -1 || dp[i] > dp[j] + 1)
                            dp[i] = dp[j] + 1;
                    }
                }
                
                return dp[len] - 1;
            }
        };
        

    状态压缩

    • 特点: 使用一个数的二进制形式保存状态,把二进制转化为十进制从而达到状态压缩

    • 位运算的常用操作:

      • 判断 j 为是否为1:(bits >> j)&1
      • 将第 j 位变为1:bits | (1 << j)
      • 将第 j 位变为0:bits & ~(1 << j)
    • 例题

      leetcode 1349. 参加考试的最大学生数

      1. 分析&实现

        这题我也不会 ——> B站看这,16:43处


    参考

    动态规划 · 二 - 坐标、双序列、划分 & 状态压缩

  • 相关阅读:
    概率密度函数 通俗理解
    宋浩《概率论与数理统计》笔记---2.2.2、连续型随机变量及其概率密度函数
    宋浩《概率论与数理统计》笔记---2.2.1、离散型随机变量及其概率分布
    宋浩《概率论与数理统计》笔记---2.1、随机变量的概念
    宋浩《概率论与数理统计》笔记---1.5.2、伯努利模型
    宋浩《概率论与数理统计》笔记---1.5.1、事件的独立性
    贝叶斯公式-汽车实例
    贝叶斯公式的理解
    宋浩《概率论与数理统计》笔记---1.4.2、贝叶斯公式
    nodemon通过配置文件监视
  • 原文地址:https://www.cnblogs.com/joe-w/p/12335957.html
Copyright © 2011-2022 走看看