动态规划训练11 [String painter HDU - 2476]
String painter
?HDU - 2476?
題意:
我認為這是一道比較難的問題,自己想了很久,沒有想出來怎么做,可能是因為思維僵化吧,一直在想怎么直接的由A變到B,事實上,可以有中間橋梁連接A和B,他們之間的關系可能往往沒有我們想的那么簡單。
依最簡單的思路,我們定義ans[i]代表區間[1...i]處,A直接變到B所需的最少次數。那么狀態轉移方程可以這樣寫
有幾種情況
(1)如果strA[i] == strB[i]的話,那么存在著一個轉移方程就是 ans[i] = min(ans[i],ans[i-1]);
(2)否則的話,那么第i個位置的字符,一定會被刷掉,此外,刷掉第i個位置的區間長度可能大于1,假設這個區間刷掉了區間[x,i]內的數,并把區間strA[x...i]內的數都刷成了strB[i]
這樣的話就相當于把區間[x...i]由空白串直接變成strB[x...i],剩下的區間[1...x-1]可以用ans[x-1]轉移過來
也就是說,轉移方程寫成ans[i] = min(ans[i],ans[x-1] + dp[x][i]),dp[x][i]表示從空白串直接變成strB[x][i]所需要用的最小次數。
下面我們的重要目標就是求出dp[i][j]來
其實到這里還是不太好想。
最右邊的字符strB[j]一定是最先被刷出來的
(1)如果strB[i] == strA[j],那么在一開始刷刷出strB[j]的時候,順手就可以把strB[i]也給刷出來,所以不需要額外的費用
dp[i][j] = dp[i+1][j]?
(2)然后我們把區間分成兩塊進行轉移(非常常規的想法)
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]);
代碼(注意我在前面的區間寫的是全閉,而在代碼里的區間寫法是左閉右開):
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int MAX = 106; char strA[MAX]; char strB[MAX]; int dp[MAX][MAX]; int ans[MAX]; int n; int main(){while(scanf("%s %s",strA,strB) != EOF){memset(dp,0,sizeof(dp));memset(ans,0,sizeof(ans));n = strlen(strA);for(int i = 0;i < n;i++) dp[i][i+1] = 1;for(int len = 2;len <= n;len++){for(int i = 0;i + len <= n;i++){dp[i][i+len] = dp[i+1][i+len] + (strB[i] == strB[i+len-1]?0:1);for(int j = i+1;j < i+len;j++){dp[i][i+len] = min(dp[i][i+len],dp[i][j]+dp[j][i+len]);} }}ans[0] = strA[0] == strB[0] ? 0:1;for(int i = 1;i < n;i++){ans[i] = dp[0][i+1];if(strB[i] == strA[i])ans[i] = min(ans[i],ans[i-1]);for(int j = 0;j < i;j++){ans[i] = min(ans[i],ans[j] + dp[j+1][i+1]);}}cout<<ans[n-1]<<endl;}return 0; }總結
以上是生活随笔為你收集整理的动态规划训练11 [String painter HDU - 2476]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 保时捷首席设计师:中国电动汽车迫使德国汽
- 下一篇: 动态规划训练12 [G - You Ar