算法与分析设计九:LCS算法和背包算法

题目

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(n
V)

源码

https://github.com/moshang1113/lsc
https://github.com/moshang1113/knapsack

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值