います\(DP \)タイトルを、我々は以下の点を考慮する必要があります:
\(1 \)状態が定義されています
\(2 \)状態遷移方程式
\(3 \)境界
\(4 \)ターゲット
その後、我々は、順番に分析します。
ステータスの定義
問題の意味によると、それは非常に簡単です:
\(F_ {I、J} \) を表し\(A \)文字列の前に\(I \)文字や\(B \)文字列の前に\(J \)最小距離手紙。
状態遷移方程式
用(F_ {I、J} \ \) 、それは間違いなく3例であろう。
\(1 \) \(a_iを\)と\(B_j \)\(ASCLL \)コードの絶対値の差
\(2 \) \(a_iを\)のスペースに対応
\(3. \) \(B_j \)のスペースに対応
もちろん、最初の方程式は、書き込みするのがベストです:\(1-F_ {I、J}の1- + | a_iを-B_j | \。。)
第二、なぜなら\(a_iを\)ある状態から、そのように、空間に対応する\(A \)文字列の前に\(I-1 \)の文字(B \)\文字列の前に\(J \)の最小距離プッシュ手紙。
したがって、第2の式は:\(1-F_ {I、J} + K \)。
同様に、第3の式は:\(F_ {I、J-K 1} + \)
\は(F_ {I、J} \) 3の最小値です。
境界
\(F_ {I、0} \) と\(F_ {0、J} \) を開始。
定義された開始、開始\(F_ {I、0} \)を表し\(A \)文字列の前に\(I \)文字や\(B \)文字列の前に\(0 \)最小距離の文字を。
それは不思議ではないですか?
だから我々は唯一の最初の文字をデフォルトすることができますので、ゼロスペースです。
\(F_ {I、0} = {F I-1,0} + K \)
簡略化は、約:\(F_ * K \ {Iは、I = 0})
同様に、\(F_ {0、J} = J * K \)
目標
セット\(A \)のランレングス(M \)\、\(B \)ランレングス\(N- \) 、ターゲットは容易である:\(F_ {M、N-} \)
\(AC \) \(コード\)
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
string a, b;
int m, n, f[2010][2010], k;
int main() {
cin >> a >> b;
cin >> k;
m = a.size(), n = b.size();
a = ' '+a, b = ' '+b;// 因为string下标从零开始,所以利用string加法的特性,开头加空格
for (int i=1; i<=m; i++)
f[i][0] = i*k;
for (int j=1; j<=n; j++)
f[0][j] = j*k;
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++) {
f[i][j] = 1e9; // 因为要取最小,所以初值要赋大
f[i][j] = min(f[i-1][j-1]+abs(a[i] - b[j]), min(f[i-1][j]+k, f[i][j-1]+k));
//求三者最小值可用min套min
}
cout << f[m][n] << endl;
return 0; // 完结撒花!
}