UVALive 4394 String painter
題目大意:有兩個字符串A,B,一次刷可以把A串一段刷成同一個字母,問至少要刷幾次才能把A串變成B串。串長≤100。
本來以為是個很簡單的區間DP,后來發現直接區間DP是不行的,這玩意有后效性:刷完一整塊之后這一塊就變了。
對于這種問題不如干脆利落一點,直接把 f[ ][ ]設成將空串(即不需要考慮A與B的相同)刷成B串的最小次數。
這個時候的轉移方程就是:
for(int i=1;i<=n;++i)f[i][i]=1;for(int len=1;len<n;++len)for(int i=1;i+len<=n;++i){int j=i+len;f[i][j]=f[i+1][j]+1;for(int k=i+1;k<=j;++k)if(B[i]==B[k])f[i][j]=min(f[i][j],f[i+1][k]+f[k+1][j]);}這個轉移方程是很巧妙的。
首先賦值最壞情況,作為最大值,然后枚舉k,進行更新。
轉移方程的思想是:如果在B串中,i和k是一樣的,就可以劃分區間進行更新。
結論:在涂色的時候,區間的一個端點,一定可以作為第一個涂色。
證明:區間涂色有兩種方法:分成左右 / 先整個涂一遍再在里面涂。
分成左右是子問題,先整個涂的話就可以先選擇這個端點涂。
所以在轉移時,如果i和k是一樣的,則可以有f[i][k]=f[i+1][k],只需要在涂k的時候把整個區間涂上就可以了。
同樣可以用上面的子問題思考方式證明。
這樣就把"空串變B串"解決了。但是我們是要把A串變B串,答案還需要統計一遍。
設g[i]表示A串從1到i全部被涂成B的最小步數,用f來更新g。
這個時候轉移方程就是這樣:
g[1]=A[1]==B[1]?0:1;for(int i=2;i<=n;++i){if(A[i]==B[i]){g[i]=g[i-1];continue;}g[i]=f[1][i];for(int j=1;j<i;++j)g[i]=min(g[i],g[j]+f[j+1][i]);}這個轉移也是比較有意思的,這里就不做分析了。
對于這種顯然只能用DP來做的、一般的轉移又有后效性的題,不妨狀態設大氣一點,直接忽略后效性帶來的影響,再變換方式統計答案。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <cstring> #include <queue> #include <complex> #include <stack> #define LL long long int #define dob double #define FILE "4394" using namespace std;const int N = 110; int n,f[N][N],g[N]; char A[N],B[N];inline int gi(){int x=0,res=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return x*res; }inline void solve(){n=strlen(A+1);for(int i=1;i<=n;++i)f[i][i]=1;for(int len=1;len<n;++len)for(int i=1;i+len<=n;++i){int j=i+len;f[i][j]=f[i+1][j]+1;for(int k=i+1;k<=j;++k)if(B[i]==B[k])f[i][j]=min(f[i][j],f[i+1][k]+f[k+1][j]);}g[1]=A[1]==B[1]?0:1;for(int i=2;i<=n;++i){if(A[i]==B[i]){g[i]=g[i-1];continue;}g[i]=f[1][i];for(int j=1;j<i;++j)g[i]=min(g[i],g[j]+f[j+1][i]);}printf("%d\n",g[n]); }int main(){freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);while(~scanf("%s%s",A+1,B+1))solve();fclose(stdin);fclose(stdout);return 0; } String painter?
轉載于:https://www.cnblogs.com/fenghaoran/p/7671155.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的UVALive 4394 String painter的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓虚拟机_[手机软件] 这款应用牛逼了
- 下一篇: 【LeetCode】053. Maxim