动态规划(3):熟练度练习(POJ 1458、最佳加法表达式、bailian2755、POJ3624、bailian1088)

这篇博客介绍了动态规划在解决最长公共子序列、最佳加法表达式、以及滑雪路线长度等实际问题中的应用。通过实例解析了动态规划的状态转移方程,并提供了相关问题的解决方案和代码示例。
摘要由CSDN通过智能技术生成

最长公共子序列

Language:Default
Common Subsequence

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 47599 Accepted: 19562

Description

A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, …, xm > another sequence Z = < z1, z2, …, zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, …, ik > of indices of X such that for all j = 1,2,…,k, x ij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.

Input

The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

Output

For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

Sample Input

abcfbc         abfcab 
programming contest
abcd mnp

Sample Output

4 
2
0

Source

线性DP基础模型 (下面会着重讲线性DP和区间DP 具体是什么到时候会讲)

输入两个串s1,s2,

设MaxLen(i,j)表示:
s1的左边i个字符形成的子串,与s2左边的j个字符形成的子串的最长公共子序列的长度(i,j从0开始算)
MaxLen(i,j) 就是本题的“状态”

假定 len1 = strlen(s1),len2 = strlen(s2)
那么题目就是要求 MaxLen(len1,len2)

套用基本思路中的定义, 我们来大致说明一下上面子问题的正确定(无严格证明)

首先我们要求字符串s1(长度为len1), s2(长度为len2)的最长公共子序列, 也就是求(len1, len2)个字符的最长公共子串。我们将问题拆分成求(i, j)个字符的最长公共子串。

正如前文说的, 他需要满足三个条件这个拆分才是成立的:具有相同的子问题*满足最优子结构*无后效性

(1)具有相同子问题:(len1, len2)可以转化为(len1 - 1, len2)和(len1, len2 - 1), 这样依次划分下去最终的问题划分结果就是(0, 0)这显然是一个可以解决的最终分割情况。

(2)满足最优子结构:我们已知(0, 0)的值是0, 这一定是最优的结构, 那么我们设(i-1, j)、(i, j-1)和(i-1, j-1)都是最优子结构, 对于(i,j)的值, 我们可以通过查看(str1[i], str2[j])的关系得来, 与之前的(i-1,j-1)无关

(3) 无后效性:每一步我们只考虑各自的(i,j)个节点, 对于后面节点的选择与前面节点的选择方式无关(这里的影响是指:在求(i,j+2)的时候与(i,j+1)以及之前的节点的选择方式无关)

(4)此题特别需要证明的一点:S1[i-1]!= s2[j-1]时,MaxLen(S1,S2)不会比MaxLen(S1,S2j-1)和MaxLen(S1i-1,S2)两者之中任何一个小,也不会比两者都大。

递推公式

if ( s1[i-1] == s2[j-1] ) //s1的最左边字符是s1[0]
    MaxLen(i,j) = MaxLen(i-1,j-1) + 1;//这里的证明暂时不证
else
    MaxLen(i,j) = Max(MaxLen(i,j-1),MaxLen(i-1,j) );

边界情况

MaxLen(n,0) = 0 ( n= 0…len1)
MaxLen(0,n) = 0 ( n=0…len2)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define maxn 1010

char str1[maxn];
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值