動態規劃淺解
阿新 • • 發佈:2022-04-06
基本概念
把多階段過程轉化為一系列單階段子問題,利用各階段之間的關係逐個求解
適用範圍
動態規劃適用的問題都具有最有子結構的性質,即原問題最優可以歸結為子問題最優
步驟
- 定義子問題
- 定義狀態轉移規則,可以理解為狀態之間的遞推關係
- 定義初始狀態
典例---字串的編輯距離求解
問題描述
定義(編輯距離)
我們要對一個字串進行若干編輯操作,編輯操作包括插入一個字元,刪除一個字元及替換一個字元。給定一個原始字串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; }
參考資料
演算法筆記-刁瑞著