LCS,01背包问题

一:问题
LCS问题和背包问题
二:解析
LCS问题:
这是一个动态规划的题目。对于可用动态规划求解的问题,有最优子结构特点
最优子结构:
设 X=(x1,x2,…xn) 和 Y={y1,y2,…ym} 是两个序列,将 X 和 Y 的最长公共子序列记为LCS(X,Y)
找出LCS(X,Y)就是一个最优化问题。因为,我们需要找到X 和 Y中最长的那个公共子序列。而要找X 和 Y的LCS,首先考虑X的最后一个元素和Y的最后一个元素。
1)如果 xn=ym,即X的最后一个元素与Y的最后一个元素相同,这说明该元素一定位于公共子序列中。因此,现在只需要找:LCS(Xn-1,Ym-1)
LCS(Xn-1,Ym-1)就是原问题的一个子问题。为什么叫子问题?因为它的规模比原问题小。
为什么是最优的子问题?因为我们要找的是Xn-1 和 Ym-1 的最长公共子序列啊。。。最长的!!!换句话说,就是最优的那个。(这里的最优就是最长的意思)
2)如果xn != ym,这下要麻烦一点,因为它产生了两个子问题:LCS(Xn-1,Ym) 和 LCS(Xn,Ym-1)
因为序列X 和 序列Y 的最后一个元素不相等,那说明最后一个元素不可能是最长公共子序列中的元素嘛。(都不相等了,怎么公共)。
LCS(Xn-1,Ym)表示:最长公共序列可以在(x1,x2,…x(n-1)) 和 (y1,y2,…yn)中找。
LCS(Xn,Ym-1)表示:最长公共序列可以在(x1,x2,…xn) 和 (y1,y2,…y(n-1))中找。
求解上面两个子问题,得到的公共子序列谁最长,那谁就是 LCS(X,Y)。用数学表示就是:
LCS=max{LCS(Xn-1,Ym),LCS(Xn,Ym-1)}
由于条件 1) 和 2) 考虑到了所有可能的情况。因此,我们成功地把原问题 转化 成了 三个规模更小的子问题。
背包问题:
状态转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
假设:
n=5, C=13, w={4,5,4,3,10}, v={9,10,9,2,24}
在这里插入图片描述
在这里插入图片描述

P[2,5]的含义是考虑前两个物品,装体积为5 的价值是10,背包体积就减少4,无法再装下第一个物品。也可以放弃第二个物品装第一个物品,价值是9,最大的是10。所以装第二个物品。
P[2,9]的含义是考虑前两个物品,装体积为5 的价值是10,背包体积就减少4,还能再装下第一个物品价值是9,总价值是19.另一种情况是舍弃第二件物品,直接装第一件物品价值是9,价值明显是装两件时候的大。
P[3,8]的含义是若装第三件物品价值加9,背包容量减少4,问题就变成了P[2,4]查表就知道P[2,4]最大是价值9,所以总价值是18;另一种情况是舍弃第三件物品,问题就变成P[2,8],查表发现最大价值是10。10明显没有18大,所以最大价值就是18。
P[3,9]的含义是若装第三件物品价值加9,背包容量减少4,问题就变成了P[2,4]查表就知道P[2,4]最大是价值9,所以总价值是18;另一种情况是舍弃第三件物品,问题就变成P[2,9],查表发现最大价值是19。19比18 大,所以最大值是19。
P[3,13]的含义是若装第三件物品价值加9,背包容量减少4,问题就变成了P[2,9]查表就知道P[2,9]最大是价值19,所以总价值是28;另一种情况是舍弃第三件物品,问题就变成P[2,13],查表发现最大价值是19。28比19大,所以最大值是28。
三:设计
LCS:
int LCS(char* X, char* Y, int m, int n) {
vector<vector >dp(m + 1, vector(n + 1));
int i, j;
for (i = 1; i < m; i++) dp[i][0] = 0;
for (j = 0; j < n; j++) dp[0][j] = 0;
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
if (X[i] == Y[j]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else if (dp[i - 1][j] >= dp[i][j - 1]) {
dp[i][j] = dp[i - 1][j];
}
else {
dp[i][j] = dp[i][j - 1];
}
}
}
return dp[m][n];
}

背包:
public static int getMaxValue(int[] weight, int[] value, int w, int n) {
// 创建一个二维数组,横列是物品的价值,竖列是物品的重量
int[][] table = new int[n + 1][w + 1];
for (int i = 1; i <= n; i++) { //物品
for (int j = 1; j <= w; j++) { //背包大小
if (weight[i] > j) {
//当前物品i的重量比背包容量j大,装不下,肯定就是不装
table[i][j] = table[i - 1][j];
} else {
//装得下,Max{装物品i, 不装物品i}
table[i][j] = Math.max(table[i - 1][j], table[i - 1][j - weight[i]] + value[i]);
}
}
}
return table[n][w];
}

四:分析
LCS复杂度:O(mn)
背包复杂度:O(n
m)n为物品数量,m为背包容量
五:源码
添加链接描述
添加链接描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值