当前位置: 首页 > wzjs >正文

一起做网店网官网青岛百度快速排名优化

一起做网店网官网,青岛百度快速排名优化,多少企业需要网站建设,网站开发大数据库在C的动态规划中,选择一维或二维DP表的核心依据是 状态变量的数量 和 状态转移的依赖关系。以下是清晰的判断逻辑和具体场景分析: 一、一维DP表 适用条件 单个状态变量:问题仅需一个参数定义状态(例如:数组下标、时间…

        在C++的动态规划中,选择一维或二维DP表的核心依据是 状态变量的数量 和 状态转移的依赖关系。以下是清晰的判断逻辑和具体场景分析:


一、一维DP表

适用条件

  1. 单个状态变量:问题仅需一个参数定义状态(例如:数组下标、时间步、容量等)。

  2. 线性依赖:当前状态仅依赖于 前序的少数状态(如dp[i]依赖dp[i-1]dp[i-2])。

典型问题

  1. 斐波那契数列

    int fib(int n) {// 边界条件:如果n小于等于1,直接返回n// 因为斐波那契数列的第0项是0,第1项是1if (n <= 1) return n;// 定义一个大小为n+1的一维数组dp,用于存储斐波那契数列的值// dp[i]表示第i个斐波那契数vector<int> dp(n+1);// 初始化dp数组的前两项// dp[0] = 0:斐波那契数列的第0项是0// dp[1] = 1:斐波那契数列的第1项是1dp[0] = 0; dp[1] = 1;// 从第2项开始,逐个计算斐波那契数列的值for (int i=2; i<=n; i++) // 状态转移方程:当前项等于前两项之和// dp[i] = dp[i-1] + dp[i-2]dp[i] = dp[i-1] + dp[i-2];// 返回第n个斐波那契数return dp[n];
    }
  2. 爬楼梯问题(每次爬1或2步):

    int climbStairs(int n) {// 定义一个大小为n+1的一维数组dp,用于存储爬楼梯问题的解// dp[i]表示爬到第i阶楼梯的方法数vector<int> dp(n+1);// 初始化dp数组的前两项// dp[0] = 1:爬到第0阶楼梯的方法数为1(理解为起点)// dp[1] = 1:爬到第1阶楼梯的方法数为1(只有一种方式:爬1步)dp[0] = 1; dp[1] = 1;// 从第2阶开始,逐个计算爬到每阶楼梯的方法数for (int i=2; i<=n; i++)// 状态转移方程:爬到第i阶楼梯的方法数等于爬到第i-1阶和第i-2阶的方法数之和// 因为每次可以爬1步或2步dp[i] = dp[i-1] + dp[i-2];// 返回爬到第n阶楼梯的方法数return dp[n];
    }
  3. 0-1背包问题(空间优化版)(注意:原始0-1背包是二维,但可用一维优化):

    int knapsack(vector<int>& weights, vector<int>& values, int capacity) {// 定义一个大小为capacity+1的一维数组dp,初始化为0// dp[j]表示背包容量为j时的最大价值vector<int> dp(capacity + 1, 0);// 遍历每个物品for (int i=0; i<weights.size(); i++) // 逆序遍历背包容量,从最大容量到当前物品的重量// 逆序更新是为了确保每个物品只被使用一次(0-1背包问题)for (int j=capacity; j>=weights[i]; j--) // 状态转移方程:选择是否将当前物品放入背包// dp[j]表示不放入当前物品时的最大价值// dp[j - weights[i]] + values[i]表示放入当前物品时的最大价值dp[j] = max(dp[j], dp[j - weights[i]] + values[i]);// 返回背包容量为capacity时的最大价值return dp[capacity];
    }

二、二维DP表

适用条件

  1. 两个状态变量:问题需要两个参数定义状态(例如:两个序列的索引、二维坐标等)。

  2. 多维依赖:当前状态依赖多个方向的状态(如左、上、左上等)。

典型问题

  1. 最长公共子序列(LCS)

    int lcs(string& s1, string& s2) {// 获取两个字符串的长度int m = s1.size(), n = s2.size();// 定义一个大小为(m+1) x (n+1)的二维数组dp,初始化为0// dp[i][j]表示s1的前i个字符和s2的前j个字符的最长公共子序列长度vector<vector<int>> dp(m+1, vector<int>(n+1, 0));// 遍历s1的每个字符for (int i=1; i<=m; i++) {// 遍历s2的每个字符for (int j=1; j<=n; j++) {// 如果当前字符相等if (s1[i-1] == s2[j-1]) // 状态转移方程:当前字符相等时,LCS长度加1dp[i][j] = dp[i-1][j-1] + 1;else // 状态转移方程:当前字符不相等时,取左边或上边的最大值dp[i][j] = max(dp[i-1][j], dp[i][j-1]);}}// 返回s1和s2的最长公共子序列长度return dp[m][n];
    }
  2. 编辑距离

    int minDistance(string s1, string s2) {// 获取两个字符串的长度int m = s1.size(), n = s2.size();// 定义一个大小为(m+1) x (n+1)的二维数组dp,初始化为0// dp[i][j]表示将s1的前i个字符转换为s2的前j个字符所需的最小操作数vector<vector<int>> dp(m+1, vector<int>(n+1, 0));// 初始化dp表的第一列:将s1的前i个字符转换为空字符串需要i次删除操作for (int i=0; i<=m; i++) dp[i][0] = i;// 初始化dp表的第一行:将空字符串转换为s2的前j个字符需要j次插入操作for (int j=0; j<=n; j++) dp[0][j] = j;// 遍历s1的每个字符for (int i=1; i<=m; i++) {// 遍历s2的每个字符for (int j=1; j<=n; j++) {// 如果当前字符相等if (s1[i-1] == s2[j-1]) // 状态转移方程:当前字符相等时,不需要操作,直接继承dp[i-1][j-1]dp[i][j] = dp[i-1][j-1];else // 状态转移方程:当前字符不相等时,取插入、删除、替换操作的最小值,并加1dp[i][j] = 1 + min({dp[i-1][j], dp[i][j-1], dp[i-1][j-1]});}}// 返回将s1转换为s2所需的最小操作数return dp[m][n];
    }
  3. 矩阵路径问题(带障碍物)

    int uniquePathsWithObstacles(vector<vector<int>>& grid) {// 获取网格的行数和列数int m = grid.size(), n = grid[0].size();// 定义一个大小为m x n的二维数组dp,初始化为0// dp[i][j]表示从起点(0,0)到点(i,j)的路径数量vector<vector<int>> dp(m, vector<int>(n, 0));// 初始化起点(0,0)的路径数量// 如果起点不是障碍物(grid[0][0] == 0),则dp[0][0] = 1,否则为0dp[0][0] = grid[0][0] == 0 ? 1 : 0;// 遍历网格的每个点for (int i=0; i<m; i++) {for (int j=0; j<n; j++) {// 如果当前点是障碍物,跳过if (grid[i][j] == 1) continue;// 如果上方有格子(i>0),则从上方格子到达当前点的路径数累加到dp[i][j]if (i>0) dp[i][j] += dp[i-1][j];// 如果左方有格子(j>0),则从左方格子到达当前点的路径数累加到dp[i][j]if (j>0) dp[i][j] += dp[i][j-1];}}// 返回到达终点(m-1,n-1)的路径数量return dp[m-1][n-1];
    }

三、如何快速判断维度?

  1. 分析问题的状态定义

    • 若问题需要同时跟踪 两个独立的变量(如两个字符串的位置、二维坐标),用二维。

    • 若问题只需一个变量(如时间、容量),用一维。

  2. 观察状态转移方程

    • 若转移方程涉及 dp[i][j] 依赖 dp[i-1][j-1] 或 dp[i][j-1],必须用二维。

    • 若转移方程仅依赖 dp[i-1] 或 dp[i-2],可以尝试一维。

  3. 特殊情况

    • 有些二维问题可以通过 滚动数组 优化为一维(如0-1背包)。

    • 但若状态依赖关系复杂(如需要左上角的值),则无法优化。


四、总结

维度适用场景示例问题状态依赖
一维DP单一状态变量,线性依赖斐波那契、爬楼梯、0-1背包优化dp[i]依赖dp[i-1]
二维DP两个状态变量,多维依赖LCS、编辑距离、矩阵路径dp[i][j]依赖左、上、左上

五、一维DP表示例:斐波那契数列

#include <iostream>
#include <vector>
using namespace std;int fibonacci(int n) {if (n <= 1) return n; // 边界条件:斐波那契数列的前两项为0和1vector<int> dp(n + 1, 0); // 定义一维DP表,dp[i]表示第i个斐波那契数dp[0] = 0; // 初始化第0项dp[1] = 1; // 初始化第1项for (int i = 2; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2]; // 状态转移方程:当前项等于前两项之和}return dp[n]; // 返回第n项的结果
}int main() {int n = 10;cout << "Fibonacci(" << n << ") = " << fibonacci(n) << endl; // 输出结果return 0;
}

代码解析

  1. 边界条件

    • 斐波那契数列的前两项是固定的:dp[0] = 0dp[1] = 1

    • 如果n <= 1,直接返回n,避免不必要的计算。

  2. DP表定义

    • vector<int> dp(n + 1, 0):定义一个大小为n+1的一维数组,初始值为0。

    • dp[i]表示第i个斐波那契数。

  3. 状态转移方程

    • dp[i] = dp[i - 1] + dp[i - 2]:当前项等于前两项之和。

    • 这是斐波那契数列的核心递推关系。

  4. 空间优化

    • 由于dp[i]只依赖于dp[i-1]dp[i-2],可以进一步优化为只使用两个变量,而不是整个数组。


六、二维DP表示例:最长公共子序列(LCS)

#include <iostream>
#include <vector>
#include <string>
using namespace std;int lcs(string& s1, string& s2) {int m = s1.size(), n = s2.size(); // 获取两个字符串的长度vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); // 定义二维DP表,dp[i][j]表示s1[0..i-1]和s2[0..j-1]的LCS长度for (int i = 1; i <= m; i++) { // 遍历s1的每个字符for (int j = 1; j <= n; j++) { // 遍历s2的每个字符if (s1[i - 1] == s2[j - 1]) { // 如果当前字符相等dp[i][j] = dp[i - 1][j - 1] + 1; // 状态转移:LCS长度加1} else { // 如果当前字符不相等dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); // 状态转移:取左边或上边的最大值}}}return dp[m][n]; // 返回最终结果
}int main() {string s1 = "abcde";string s2 = "ace";cout << "LCS length: " << lcs(s1, s2) << endl; // 输出结果return 0;
}

代码解析

  1. DP表定义

    • vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)):定义一个大小为(m+1) x (n+1)的二维数组,初始值为0。

    • dp[i][j]表示字符串s1的前i个字符和s2的前j个字符的最长公共子序列长度。

  2. 状态转移方程

    • 如果s1[i-1] == s2[j-1],则dp[i][j] = dp[i-1][j-1] + 1

    • 如果s1[i-1] != s2[j-1],则dp[i][j] = max(dp[i-1][j], dp[i][j-1])

  3. 初始化

    • dp[0][j]dp[i][0]都初始化为0,因为空字符串与任何字符串的LCS长度为0。

  4. 遍历顺序

    • 外层循环遍历s1,内层循环遍历s2,确保每个子问题都被正确计算。

  5. 结果

    • dp[m][n]即为两个字符串的最长公共子序列长度。


七、动态规划的核心知识点

  1. 状态定义

    • 明确dp[i]dp[i][j]表示什么。例如:

      • 斐波那契数列:dp[i]表示第i个斐波那契数。

      • LCS问题:dp[i][j]表示s1[0..i-1]s2[0..j-1]的最长公共子序列长度。

  2. 状态转移方程

    • 描述当前状态与之前状态的关系。例如:

      • 斐波那契数列:dp[i] = dp[i-1] + dp[i-2]

      • LCS问题:dp[i][j] = dp[i-1][j-1] + 1(如果字符相等),否则dp[i][j] = max(dp[i-1][j], dp[i][j-1])

  3. 初始化

    • 根据问题的边界条件初始化DP表。例如:

      • 斐波那契数列:dp[0] = 0dp[1] = 1

      • LCS问题:dp[0][j] = 0dp[i][0] = 0

  4. 遍历顺序

    • 确保在计算dp[i][j]时,所依赖的状态已经计算完成。

  5. 空间优化

    • 如果状态转移只依赖于有限的前几个状态,可以优化空间复杂度。例如:

      • 斐波那契数列:用两个变量代替整个数组。

      • 0-1背包问题:用一维数组代替二维数组。


八、总结

  • 一维DP表:适用于状态变量单一、依赖关系简单的问题(如斐波那契数列、爬楼梯问题)。

  • 二维DP表:适用于状态变量有两个、依赖关系复杂的问题(如LCS、编辑距离)。

  • 核心步骤:定义状态、写出状态转移方程、初始化、确定遍历顺序、优化空间(可选)。

http://www.dtcms.com/wzjs/345002.html

相关文章:

  • 网站怎么收录网站seo综合诊断
  • 网站系统管理员模块网店推广策划书
  • 南宁新技术产业建设开发总公司网站软件开发培训机构排名
  • ubc网站谁做的网络营销案例分析题
  • 图片网站怎么做优化seo分析师
  • 徐州开发区中学网站世界十大搜索引擎及地址
  • 做企业宣传片的网站seoul是哪个国家
  • 怎么做网站扫码支付seo网络优化
  • php的网站网站关键词优化排名
  • 网站建设税收编码下载百度安装
  • 温州公司建设网站制作长春网站seo公司
  • 网站建设课程设计心得电脑优化软件哪个好用
  • 1688批发网官网seo快速推广
  • 国内erp系统排名太原seo排名公司
  • 网站开发亿玛酷定制哈尔滨百度关键词优化
  • 如何申请自己的网站百度最新秒收录方法2021
  • 如何提升线上销售的方法seo长尾关键词优化
  • 德宏北京网站建设南宁seo推广服务
  • 网站关键字可以做几个太原百度推广排名优化
  • 连云港网站定制开发营销网站搭建
  • 江苏建站系统佛山企业用seo策略
  • wordpress 云数据库谷歌seo公司
  • 山西教育学会网站建设发布信息的免费平台有哪些
  • wordpress smtp设置163网站seo站群软件
  • 省级建设主管部门网站指数型基金是什么意思
  • 发布建设网站太原建站seo
  • 平台是什么意思郑州seo公司
  • 上海企业展厅设计公司seo搜索引擎优化方案
  • 在家帮诈骗团伙做网站市场推广计划方案模板
  • 海参企业网站怎么做百度总部客服电话