LA 4394 String painter
2015-10-08 23:10
507 查看
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,.代码:
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 ,s2 ; int dp ; int ans ; 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]); } }
相关文章推荐
- POJ 1159
- 区间DP poj 2955 hdu 2476
- UVALive 4857 Halloween Costumes(区间DP)
- HDU 1028(Ignatius and the Princess III)区间DP之整数划分
- Brackets Sequence
- POJ 2955 Brackets(区间DP水题)
- CodeForces 149D Coloring Brackets(区间DP+dfs)
- UVALive 4394 String painter
- hdu 4745 Two Rabbits
- ZOJ 3541 The Last Puzzle
- Code Jam 2009 Round1C Problem C. Bribe the Prisoners —— 区间DP
- UVA 10003 —— 区间DP
- POJ 3042 Grazing on the Run (区间DP)
- UVA 10003 Cutting Sticks(区间dp)
- SPOJ - GCJ1C09C Bribe the Prisoners
- NYOJ15 - UVA1626 括号匹配问题(区间dp)
- wikioi 1154 - 能量项链 (环形区间dp)
- POJ 1651 - Multiplication Puzzle(区间DP,矩阵链乘三种模版详解)
- SMU 1106 - 凸多边形的最优三角剖分问题(区间DP)
- wikioi1085 - 数字游戏(区间DP或者划分DP)