算法设计与分析第4章 动态规划(二)【DP序列问题】

第3章 动态规划(二)【DP序列问题】

3.2 DP序列问题

(51nod的动态规划教程很不错,讲解很详细,以下分析来自51nod)

1.矩阵取数问题

给定一个m行n列的矩阵,矩阵每个元素是一个正整数,你现在在左上角(第一行第一列),你需要走到右下角(第m行,第n列),每次只能朝右或者下走到相邻的位置,不能走出矩阵。走过的数的总和作为你的得分,求最大的得分。

分析:
从起点到终点的最优路径上经过了(m + n – 1)个点,则这条路径上对应起点到这(m + n – 1)个点的子路径也都从起点到该位置的所有路径中和最大的路径。

定义f(int x,int y)表示从起点到第x行第y列的最优路径上的数之和,有从起点达到x,y的最优路径有两种可能:
要么f(x – 1, y) + A[x][y]
要么f(x, y – 1) + A[x][y]
所以,f(x, y) = max(f(x – 1, y) , f(x, y – 1) ) + A[x][y]

初值:
f(1,1)是起点,没的选f(1,1) = A[1][1]。
按照递推式 f(1,2) = max(f(0, y) , f(1,1)) + A[1][2],考虑实际意义,这表示要么从上面到达(1,2)要么从左面到达(1,2),可是上面没有位置,说明没的选。所以可以定义f(0, y) = -∞, 同理f(x, 0) = -∞。

递推式:
在这里插入图片描述

输入

第1行:N,N为矩阵的大小。(2 <= N <= 500)
第2 - N + 1行:每行N个数,中间用空格隔开,对应格子中奖励的价值。(1 <= N[i] <= 10000)

输出

输出能够获得的最大价值。

输入示例

3
1 3 3
2 1 3
2 2 1

输出示例

11

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
   
   
	int n,i,j;
	int a[505][505];
	while(cin>>n)
	{
   
   
		for(i=0; i<n; i++)
		{
   
   
			a[0][i]=0;
			a[i][0]=0;
		}
		for(i=1; i<=n; i++)
		{
   
   
			for(j=1; j<=n; j++)
			{
   
   
				cin>>a[i][j];
			}
		}
		for(i=1; i<=n; i++)
		{
   
   
			for(j=1; j<=n; j++)
			{
   
   
				a[i][j]=max(a[i-1][j],a[i][j-1])+a[i][j];
			}
		}
		cout<<a[n][n]<<endl;
	}
	return 0;
} 

2.编辑距离问题

给定两个字符串S和T,对于T我们允许三种操作:
(1) 在任意位置添加任意字符
(2) 删除存在的任意字符
(3) 修改任意字符
问最少操作多少次可以把字符串T变成S?

例如: S= “ABCF” T = “DBFG”
那么可以
把D改为A
(2) 删掉G
(3) 加入C
所以答案是3。

分析:
给定字符串S和T,可以用一种特殊字符促成两个字符串的对齐。特殊字符是“-”, 允许在S和T中任意添加这种特殊字符使得它长度相同,然后让这两个串“对齐”,最终两个串相同位置出现了不同字符,就扣1分,要使得这两个串对齐扣分尽量少。

对于例子,采取这样的对齐方式:
12345
ABCF-
DB-FG
注意:如果要对齐,两个“-”相对是没有意义的,所以要求不出现这种情况。

那么:
(1) S,T对应位置都是普通字符,相同,则不扣分。 例如位置2,4
(2) S,T对应位置都是普通字符,不同,则扣1分。 例如位置1
(3) S在该位置是特殊字符,T在该位置是普通字符,则扣1分,例如位置5
(4) S在该位置是普通字符,T在该位置是特殊字符,则扣1分,例如位置3

扣分项目对应:
(1) 不扣分,直接对应
(2) 对应把T中对应位置的字符修改
(3) 对应在T中删除该字符
(4) 对应在T中添加该字符

设f(i,j)表示S的前i位和T的前j位对齐后的最少扣分。

最后一位对齐的情况:

(1) S[i] == T[j], 这时前i – 1和j – 1位都已经对齐了,这部分肯定要最少扣分。这种情况下最少的扣分是f(i-1,j-1)
(2) S[i]≠T[j],这种情况下最少的扣分是f(i -1, j – 1) + 1
(3) S的前i位和T的前(j – 1)位已经对齐了,这部分扣分也要最少。这种情况下最少的扣分是f(i,j-1) + 1
(4) S的前(i-1)位已经和T的前j位对齐了,这部分扣分要最少。这种情况下最少的扣分是f(i,j-1) + 1
具体f(i,j)取什么值,要看哪种情况的扣分最少。

递推式:

f(i,j) = min(f(i – 1, j – 1) + same(i,j), f(i – 1,j ) + 1, f(i, j – 1) + 1)

初值:
因为对于S的前0位,我们只能在之前加入“-”,或者说把T全部删掉了。类似地,对于T地前0位,我们只能把S的字符都加进来,别无选择。

f(0, j) = j
f(i, 0) = i

输入

第1行:字符串a(a的长度 <= 1000)。
第2行:字符串b(b的长度 <= 1000)。

输出

输出a和b的编辑距离

输入示例

kitten
sitting

输出示例

3

代码:

#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
char str1[1005],str2[1005
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值