动态规划浅解

基本概念

    把多阶段过程转化为一系列单阶段子问题,利用各阶段之间的关系逐个求解

适用范围

    动态规划适用的问题都具有最优子结构的性质,即原问题最优可以归结为子问题最优

步骤

  1. 定义子问题
  2. 定义状态转移规则,可以理解为状态之间的递推关系
  3. 定义初始状态

典例---字符串的编辑距离求解

问题描述

定义(编辑距离)

    我们要对一个字符串进行若干编辑操作,编辑操作包括插入一个字符,删除一个字符及替换一个字符。给定一个原始字符串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;
}

参考资料

算法笔记-刁瑞著

posted @ 2022-04-06 20:04  嗯嗯魑嗯嗯  阅读(33)  评论(0编辑  收藏  举报