String painter
题目描述
有两个长度相等,都只由小写字母构成的字符串A和B. 现在你有一把充满魔♂力的刷子。使用这把刷子,你可以把字符串中连续的一段区间刷♂成一个相同的字符,例如,对于字符串"vandarkholme",把区间[3,6]刷成'd',可以变成"vanddddholme"。现在你要用这把刷♂子把字符串A变成B,最少要刷多少次?
输入
多组数据,每组数据都有两行:
第一行是字符串A.
第二行是字符串B.
字符串长度不超过100.
输出
在单独的一行中输出结果
样例输入
zzzzzfzzzzz abcdefedcba abababababab cdcdcdcdcdcd
样例输出
6 7
好久没写区间dp了
之前写过几道区间dp但是基本思想并不是跟理解
正好今天借机复习一下区间dp
的确区间dp就是不断的进行区间合并而找到最优解
根据本题我们不能直接合并因为之间所需要考虑的状态较多
所以我们分两次进行dp
第一次考虑直接图空色
第二次枚举原来的颜色
#include<bits/stdc++.h>
using namespace std;
char s1[105];
char s2[105];
int dp[105][105];
int f[105];
int main()
{
while(~scanf("%s",s1+1))
{
memset(dp,0x3f,sizeof(dp));
memset(f,0x3f,sizeof(f));
scanf("%s",s2+1);
int n=strlen(s1+1);
for(int len=0;len<n;len++)
{
for(int i=1;i<=n;i++)
{
int j=i+len;
if(len==0)
{
dp[i][j]=1;
continue;
}
dp[i][j]=min(dp[i][j],dp[i+1][j]+(s2[i]!=s2[i+1]));
dp[i][j]=min(dp[i][j],dp[i+1][j]+(s2[i]!=s2[j]));
dp[i][j]=min(dp[i][j],dp[i][j-1]+(s2[j]!=s2[j-1]));
dp[i][j]=min(dp[i][j],dp[i][j-1]+(s2[j]!=s2[i]));
for(int k=i+1;k<j;k++)
{
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
}
}
}
// cout<<dp[1][n]<<" "<<dp[1][1]<<endl;
f[1]=1;
f[0]=0;
for(int i=1;i<=n;i++)
{
if(s1[i]==s2[i]) f[i]=f[i-1];
else
{
for(int k=0;k<i;k++)
{
f[i]=min(f[i],f[k]+dp[k+1][i]);
}
}
}
printf("%d
",f[n]);
}
}