算法复习——动态规划
2021-03-08 20:28
标签:str 大于 关系 容量 背包 line 分析 大连 连续 0-1背包问题、最大连续子数组问题、最长公共子序列、最长公共子串、最小编辑距离、钢条切割、矩阵链乘 动规方程: 用\(p[i,c]\)表示前i个物品在背包容量为c时能选择的最大价值。 \(dp[i,c] = max\{dp[i-1,c-v_i] + p_i, dp[i-1,c]\}\) 所以0-1背包问题就是求\(p[n,C]\) 伪代码: 时间复杂度:\(O(n*c)\) 总结,解决0-1背包问题的思路: D[i]表示以X[i]开头的最大子数组的和,所以要从后往前计算 如果用dp[i]表示以X[i]结尾的最大子数组的和,则从前往后计算 时间复杂度\(O(n)\) 原始问题:X[1..n] Y[1..m]两个字符串,求其最长公共子序列 用dp[i][j]表示X[1..i], Y[1..j]的最长公共子序列长度 递推式: \(if X[i] == Y[j]: dp[i][j] = dp[i-1][j-1] + 1;\) \(else: dp[i][j] = max\{dp[i][j-], dp[i-1][j]\}\) 时间复杂度\(O(n*m)\) 子序列不要求连续,但是子串要求是连续的 递推式: \(if X[i] == Y[j]: dp[i][j] = dp[i-1][j-1] + 1;\) \(else: dp[i][j] = 0\) 伪代码: 时间复杂度\(O(n*m)\) 有点复杂,最后复习 下面这两个是同一种类型的,都需要遍历子问题 C[i]表示切割长度为i的钢条所能获得的最大收益 $C[i] = max_{1\le j\le i-1}{p[j] + C[i-j]], p[i]} $ 时间复杂度为:\(O(n^2)\) 明确原始问题: 明确原始问题 ??[??, ??]:计算矩阵链????..??所需标量乘法的最小次数 递推关系建立: 分析最优(子)结构 建立动规方程: 用\(dp[i][j]\)表示第i个矩阵乘到第j个矩阵所需要的最小乘法次数 \(dp[i][j] = min_{i \le k \le j-1}\{dp[i][k]+dp[k+1][j] + p_{i-1}*p_k*p_j \}\) 确定计算顺序: 算法复习——动态规划 标签:str 大于 关系 容量 背包 line 分析 大连 连续 原文地址:https://www.cnblogs.com/VanHa0101/p/14193114.html
动态规划问题的一般步骤:
0-1背包
//初始化
for(i=0 to C) { //前0个物品,背包容量是C时
dp[0][i] = 0;
}
for(i=0 to n) { //前i个物品,背包容量是0时
dp[i][0] = 0;
}
//i表示前i个物品
for(i=1 to n) {
//j表示当前背包容量
for(j=1 to C) {
// 如果选择这个物品装入背包
if ((v[i] dp[i-1][j])){
dp[i][j] = dp[i-1][j-v[i]] + p[i];
}
// 如果背包容量装不下v[i]或者装入背包后总价值变小,那么选择不装入
else {
dp[i][j] = dp[i-1][j];
}
}
}
// 选择最优的方案
return dp[n][C];
最大连续子数组问题
dp[n] = X[n]
max = dp[n];
for(i=n-1 to 1) {
//如果以X[i+1]开头的最大子数组的和dp[i+1]大于0,那么以X[i]开头的最大子数组的和dp[i]等于X[i]+ dp[i+1]
if(dp[i+1] > 0) {
dp[i] = dp[i+1] + X[i];
}
else {
dp[i] = X[i]
}
if(dp[i] > max) {
max = dp[i];
}
}
return max;
最长公共子序列
// 初始化
for(i=1 to n) {
dp[i][0] = 0;
}
for(j=1 to m) {
dp[0][j] = 0;
}
//
for(i=1 to n) {
for(j=1 to m) {
if(X[i] == Y[j]) {
dp[i][j] = dp[i-1][j-1] + 1;
}
else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[n][m]
最长公共子串
// 初始化
for(i=1 to n) {
dp[i][0] = 0;
}
for(j=1 to m) {
dp[0][j] = 0;
}
//
for(i=1 to n) {
for(j=1 to m) {
if(X[i] == Y[j]) {
dp[i][j] = dp[i-1][j-1] + 1;
}
else {
dp[i][j] = 0;
}
}
}
return dp[n][m]
最小编辑距离
钢条切割
c[0] = 0;
for(i=1 to n) {
q = p[i]; // 不切割
for(j=1 to i-1) { // 枚举子问题,找最大值
if (p[j]+C[i-j] > q) {
q = p[j] + C[i-j]
}
}
C[i] = q;
}
return C[n]
矩阵链乘
dp[1..n][1..n] = INF;
for(i=1 to n) { //如果只有一个矩阵,乘法次数为0
dp[i][i] = 0;
}
for(l=2 to n) { // 区间长度
for(i=1 to n-l+1) {//区间左端点
j = i+l-1; // 区间右端点
for(k=i to j-1) {
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j]);
}
}
}
return dp[1][n];
上一篇:C++初级项目——机房预约系统
下一篇:C语言中的错误处理