标签: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]\)
伪代码:
//初始化
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] < C) and ( dp[i-1][j-v[i]] + p[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];
时间复杂度:\(O(n*c)\)
总结,解决0-1背包问题的思路:
D[i]表示以X[i]开头的最大子数组的和,所以要从后往前计算
如果用dp[i]表示以X[i]结尾的最大子数组的和,则从前往后计算
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;
时间复杂度\(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]\}\)
// 初始化
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]
时间复杂度\(O(n*m)\)
子序列不要求连续,但是子串要求是连续的
递推式:
\(if X[i] == Y[j]: dp[i][j] = dp[i-1][j-1] + 1;\)
\(else: dp[i][j] = 0\)
伪代码:
// 初始化
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]
时间复杂度\(O(n*m)\)
有点复杂,最后复习
下面这两个是同一种类型的,都需要遍历子问题
C[i]表示切割长度为i的钢条所能获得的最大收益
$C[i] = max_{1\le j\le i-1}{p[j] + C[i-j]], p[i]} $
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]
时间复杂度为:\(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 \}\)
确定计算顺序:
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];
标签:str 大于 关系 容量 背包 line 分析 大连 连续
原文地址:https://www.cnblogs.com/VanHa0101/p/14193114.html