HUD 2746
Problem Description
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can change a segment of characters of a string to any other character you want. That is, after using the painter, the segment is made up of only one kind of character. Now your task is to change A to B using string painter. What’s the minimum number of operations?
Input
Input contains multiple cases. Each case consists of two lines:
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
Output
A single line contains one integer representing the answer.
Sample Input
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd
Sample Output
6
7
题意:给定两个字符串A,B,每次都能把一段区间刷成同一种字符,求A刷成B最少要刷多少次?
关键词:区间dp+线性dp
思路:f[i][j]:【i,j】,从空串刷成B最少需要的次数 (区间dp)
dp[i]: 【0,i】从A刷成B最少需要的次数 (线性dp)
f[i][j] :
初始化:f[i][i]=1; //每个字符就是一个区间
(1)考虑首尾分
若b[i]=b[j],即首尾字符相同,则第i个可以不考虑 f[i][j]=f[i+1][j];
同理,若b[i]=b[i+1],则第i个可以不考虑 f[i][j]=f[i+1][j];
若b[i]=b[j]和b[i]=b[i+1]都不满足,则 f[i][j]=f[i+1][j]+1(+1要分两段刷,多刷一次)
同理上述三行,若b[i]=b[j],则第j个可以不考虑 f[i][j]=f[i][j-1];
若b[j]=b[j-1],则第j个可以不考虑 f[i][j]=f[i][j-1];
若b[i]=b[j]和b[j]=b[j-1]都不满足,则 f[i][j]=f[i][j-1]+1(+1要分两段刷,多刷一次)
(2)考虑中间分
f[i][j]=min{f[i][j], f[i][k]+f[k+1][j]} (i<=k<j)
dp【i】 经典线性模型
初始化 dp[i]=dp[0][i]
若a[i]=b[i], dp[i]=min{dp[i-1],dp[i]};
否则,dp[i]=min{dp[i],dp[k]+f[k+1][i]} 0<=k<i
#include<iostream>
#include<cstring>
using namespace std;
const int N=105;
int dp[N],f[N][N],n;
//f[i][j]:从空串到b的最少要花多少步
//dp[i]:[1...i],a到b最少要花多少步
int main()
{
string a,b;
while(cin>>a>>b){
n=a.size();
for(int i=0; i<n; i++){
f[i][i]=1;
}
for(int len=2; len<=n; len++){
for(int i=0;i+len-1<=n; i++){
int j=i+len-1;
f[i][j]=0x7fffffff;
f[i][j]=min(f[i][j],f[i+1][j]+(b[i]!=b[j]&&b[i]!=b[i+1]));
f[i][j]=min(f[i][j],f[i][j-1]+(b[i]!=b[j]&&b[j]!=b[j-1]));
for(int k=i; k<j; k++){
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
}
}
}
for(int i=0; i<n; i++){
dp[i]=f[0][i];//这里初始化错了
if(a[i]==b[i]){
if(i==0) dp[0]=0;//dp[i-1]这里要单独处理
else
dp[i]=min(dp[i-1],dp[i]);
}
else{
for(int k=0; k<i; k++){
dp[i]=min(dp[i],dp[k]+f[k+1][i]);
}
}
}
cout<<dp[n-1]<<endl;
}
return 0;
}