LA 4394 String painter

1.題目描述:點擊打開鏈接

2.解題思路:本題是區間dp類的問題,根據題意描述,要求我們把給定的A串變成B串,每次操作時候可以選一段區間,然後將這個區間都刷成同一個字符,詢問最少需要多少步。因爲A串和B串部分位置可能相同,爲了便於分析,讓我們先忘掉A串,從一個空串考慮起。

按照以往的經驗,我們可以設dp(i,j)表示把字符串A中的i...j變成字符串B中的i...j需要的最少步數。多次嘗試後可以發現,如果我們刷同一個字符串,一定是希望刷的越長越好。根據題意不難得知長區間的結果依賴於短區間,那麼不難得到如下的狀態轉移方程:

dp(i,j)=dp(i+1,j)+1; 

dp(i,j)=min{dp(i+1,k)+dp(k+1,j)}; (b[i]==b[k])

第一個方程表示單刷第i位的字符。第二個方程表示如果b[i]==b[k]時候,那麼刷第k位的時候也可以同時刷第i位,因此只需要dp(i+1,k)即可表示dp(i,k)的結果了。由於長區間依賴短區間的結果,那麼可以實現從小到大枚舉尾部,然後再從大到小枚舉頭部。這樣,每次需要的區間一定是之前計算過的。

計算出dp數組,還並沒有得到答案。因爲dp表示的是A串和B串完全不同時候,最少需要幾步。接下來考慮利用dp數組和A數組來得到最終的結果。此時可以用ans[i]表示字符串A中0..i變成字符串B的0..i所需的最小步數。那麼當A[i]==B[i]時候,ans[i]=ans[i-1],否則,則遍歷0..i之間的所有分法。即ans[i]=min{ans[k],dp(k+1,i)}。這樣,最後的答案就是ans[len-1]。

3,.代碼:

#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<list>
#include<complex>
#include<functional>
using namespace std;

#define me(s) memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
typedef long long ll;
typedef pair <int,int> P;


const int N=100+10;

char s1[N],s2[N];

int dp[N][N];
int ans[N];

int main()
{
    while(~scanf("%s%s",s1,s2))
    {
        int len=strlen(s1);
        me(dp);
        for(int j=0;j<len;j++)//j是尾部
            for(int i=j;i>=0;i--)//i是頭部
        {
            dp[i][j]=dp[i+1][j]+1; //單刷第i位
            for(int k=i+1;k<=j;k++)
                if(s2[i]==s2[k]) //如果相等,說明i,k兩位可以同時刷,更新答案
                dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
        }
        for(int i=0;i<len;i++)
            ans[i]=dp[0][i];
        for(int i=0;i<len;i++)
            if(s1[i]==s2[i]) ans[i]=ans[i-1];//相等,那麼第i位不需要改動
            else for(int j=0;j<i;j++) //否則,分成2段考慮
                ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
        printf("%d\n",ans[len-1]);
    }
}


發佈了470 篇原創文章 · 獲贊 90 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章