1. 程式人生 > 其它 >動態規劃淺解

動態規劃淺解

基本概念

    把多階段過程轉化為一系列單階段子問題,利用各階段之間的關係逐個求解

適用範圍

    動態規劃適用的問題都具有最有子結構的性質,即原問題最優可以歸結為子問題最優

步驟

  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; }

參考資料

演算法筆記-刁瑞著