题目
LCS:给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence)
01背包:有n件物品,每件物品的重量为w[i],价值为c[i]。现有一个容量为V的背包,问如何选取物品放入背包,使得背包内物品的总价值最大
解析
LCS:
X=<A,B,C,E,A>
Y=<B,A,C,B>
m=0-5
n=0-4
(1)X=5,Y=4
查表(5,4) “2;删除y”
X=<A,B,C,E,A>
Y=<B,A,C,B>
=>
X=<A,B,C,E,A>
Y=<B,A,C>
(2)X=5,Y=3
查表(5,3) “2;删除y”
X=<A,B,C,E,A>
Y=<B,A,C>
=>
X=<A,B,C,E,A>
Y=<B,A>
(3)X=5,Y=2
查表(5,2) “2;删除两个”
X=<A,B,C,E,A>
Y=<B,A>
=>
X=<A,B,C,E>
Y=< B>
输出A
(4)X=4,Y=1
查表(4,1) “1;删除x”
X=<A,B,C,E>
Y=< B>
=>
X=<A,B,C>
Y=< B>
(4)X=3,Y=1
查表(3,1) “1;删除x”
X=<A,B,C>
Y=< B>
=>
X=<A,B>
Y=< B>
(5)X=2,Y=1
查表(2,1) “1;删两个”
X=<A,B>
Y=< B>
=>
X=< A>
Y=<>
输出B
(6)X=1,Y=0
算法结束,最终输出<A,B>
01背包:
n=4 V=10
w0=1,w2=3,w3=5,w4=7
c0=1,c2=2,c3=3,c4=4
i=0
v=10 dp[10]=max(dp[10],dp[10-w[1]+c[0]=1
v=9 dp[9]=max(dp[9],dp[9-w[1]+c[0]=1
v=8 dp[8]=max(dp[8],dp[8-w[1]+c[0]=1
v=7 dp[7]=max(dp[7],dp[7-w[1]+c[0]=1
v=6 dp[6]=max(dp[6],dp[6-w[1]+c[0]=1
v=5 dp[5]=max(dp[5],dp[5-w[1]+c[0]=1
v=4 dp[4]=max(dp[4],dp[4-w[1]+c[0]=1
v=3 dp[3]=max(dp[3],dp[3-w[1]+c[0]=1
v=2 dp[2]=max(dp[2],dp[2-w[1]+c[0]=1
v=1 dp[1]=max(dp[1],dp[1-w[1]+c[0]=1
i=1
v=10 dp[10]=max(dp[10],dp[10-w[3]+c[1]=3
v=9 dp[9]=max(dp[9],dp[9-w[3]+c[1]=3
v=8 dp[8]=max(dp[8],dp[8-w[3]+c[1]=3
v=7 dp[7]=max(dp[7],dp[7-w[3]+c[1]=3
v=6 dp[6]=max(dp[6],dp[6-w[3]+c[1]=3
v=5 dp[5]=max(dp[5],dp[5-w[3]+c[1]=3
v=4 dp[4]=max(dp[4],dp[4-w[3]+c[1]=3
v=3 dp[3]=max(dp[3],dp[3-w[3]+c[1]=2
i=2
v=10 dp[10]=max(dp[10],dp[10-w[5]+c[2]=6
v=9 dp[9]=max(dp[9],dp[9-w[5]+c[2]=6
v=8 dp[8]=max(dp[8],dp[8-w[5]+c[2]=5
v=7 dp[7]=max(dp[7],dp[7-w[5]+c[2]=4
v=6 dp[6]=max(dp[6],dp[6-w[5]+c[2]=4
v=5 dp[5]=max(dp[5],dp[5-w[5]+c[2]=3
i=3
v=10 dp[10]=max(dp[10],dp[10-w[7]+c[3]=6
v=9 dp[9]=max(dp[9],dp[9-w[7]+c[3]=6
v=8 dp[8]=max(dp[8],dp[8-w[7]+c[3]=5
v=7 dp[7]=max(dp[7],dp[7-w[7]+c[3]=4
dp[10]=6
设计
LCS:
void LCS(int len1, int len2){
int i, j;
for(i = 0; i <= len1; i++) //将第一列设置0
c[i][0] = 0;
for(j = 1; j <= len2; j++) //第一行设置为0
c[0][j] = 0;
for(i = 1; i<= len1; i++){ //用1,0,-1三个整形作为上下斜上的方向标记
for(j = 1; j <= len2; j++){
if(s1[i-1] == s2[j-1]){ //如果最后一个字符相同,那么在剩下的里找
c[i][j] = c[i-1][j-1] + 1;
d[i][j] = 1;
}
else if(c[i-1][j] >= c[i][j-1]){
c[i][j] = c[i-1][j];
d[i][j] = 0;
}
else{
c[i][j] = c[i][j-1];
d[i][j] = -1;
}
}
}
}
背包:
for(v = 0; v <= V; v++){
dp[v] = 0;
}
for(i = 0; i < n; i++){
cout<<"i="<<i<<endl;
for(v = V; v >= w[i]; v--){
// 状态转移方程
// dp[v] = max(dp[v], dp[v-w[i]]+c[i]);
if(dp[v]<dp[v-w[i]]+c[i])dp[v]=dp[v-w[i]]+c[i];
}
}
// 寻找dp[0...V]中的最大即为答案
max = 0;
for(v = 0; v <= V; v++){
if(dp[v] > max)
max = dp[v];
}
分析
LSC:O(nm)
0/1背包:O(nV)
源码
https://github.com/moshang1113/lsc
https://github.com/moshang1113/knapsack