动态规划浅解
基本概念
把多阶段过程转化为一系列单阶段子问题,利用各阶段之间的关系逐个求解
适用范围
动态规划适用的问题都具有最优子结构的性质,即原问题最优可以归结为子问题最优
步骤
- 定义子问题
- 定义状态转移规则,可以理解为状态之间的递推关系
- 定义初始状态
典例---字符串的编辑距离求解
问题描述
定义(编辑距离)
我们要对一个字符串进行若干编辑操作,编辑操作包括插入一个字符,删除一个字符及替换一个字符。给定一个原始字符串S1和一个目标字符串S2,我们将S1到S2的编辑距离定义为S1修改成S2所需的最小编辑次数。
例:hat到what的编辑距离是1,即插入w
动态规划算法
1.定义子问题
我们计S1的字符串长度为n1,S2的字符串长度为n2,记S(i)表示字符串S的第i个字符,计d[i,j]表示S1的前i个字符所构成的前缀与S2的前j个字符所构成的前缀之间的编辑距离,显然的d[n1,n2]就是我们最终要求的编辑距离。
2.定义状态转移规则
这个式子包含了几种情况,如果S1(i)=S2(j),那么只需要考虑S1的前i-1个字符与S2的前j-1个字符;如果S1(i)≠S2(i),那么需要考虑对S1的末尾进行插入,删除和替换三种情况。
3.定义初始状态
1.d[i,0] = i (i次删除操作)
2.d[0,j] = j (j次插入操作)
完成上述三步操作我们就可进行代码编写了
#include<stdio.h> #include<string.h> int min(int x,int y,int z) { int r; if(x <= y) r = x; else r = y; if(r <= z) return r; else return z; } int main() { char a[10]; char b[10]; gets(a); gets(b); int len1,len2; len1 = strlen(a); len2 = strlen(b); int d[10][10]; int i,j; for(j = 0;j <= len2;j++) d[0][j] = j; for(i = 0;i <= len1;i++) d[i][0] = i; for(i = 1;i <= len1;i++) for(j = 1;j <= len2;j++) { if(a[i-1] == b[j-1]) d[i][j] = d[i-1][j-1]; else d[i][j] = min(d[i][j-1],d[i-1][j],d[i-1][j-1]) + 1; } printf("%d",d[len1][len2]); return 0; }
参考资料
算法笔记-刁瑞著