区间dp [H - String painter]
区间dp H - String painter
题目大意:
给你两个字符串 \(s1\) 和 \(s2\) ,你每次可以对一段区间更新成同一种颜色,问最少更新多少次可以把 \(s1\) 更新成 \(s2\)
题解:
- 首先把这个当成一个空白字符串进行求解,这个B - Halloween Costumes 已经写过如何求解
- 然后在对于两个不同的字符串具体进行操作使得最后的更新次数比更新一个空白字符串要少。
- 对于位置 \(i\) 如果 \(s1[i]==s2[i]\) 则此时的更新次数就等于到 \(i-1\) 这位置的更新次数
- 如果 \(s1[i]!=s2[i]\) 那么此时的更新次数等于:\(i\) 之前的一个位置 \(j\) 的次数+\(dp[i][j]\)
如果已经一个字符串更新成我需要的字符串的最少次数,那么对于一个已知的字符串,想要更新成需要的字符串,这个问题就是一个简单的 \(dp\)。
这个题目和B - Halloween Costumes 这个题目相比较,两个题目很像,只是本题已经给了一个字符串了,所以可能可以减少这个更新的次数。
自己没有想清楚,如果之前的哪个题目会写了,这个题目应该也要会写才对。
#include <bits/stdc++.h>
#define id first
#define val second
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=110;
typedef long long ll;
int dp[maxn][maxn],f[maxn];
char s1[maxn],s2[maxn];
void init(int n){
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++) dp[i][j]=0;
}
}
int main(){
while(scanf("%s%s",s1+1,s2+1)!=EOF){
int n=strlen(s1+1);
init(n);
for(int i=1;i<=n;i++) {
dp[i][i]=1;
}
for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
dp[i][j]=dp[i+1][j]+1;
for(int k=i+1;k<=j;k++){
if(s2[k]==s2[i]) dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]);
}
}
}
for(int i=1;i<=n;i++){
f[i] = i;
if (s1[i] == s2[i]) f[i] = f[i - 1];
else {
for (int j = 1; j <= i; j++)
f[i] = min(f[i], f[j - 1] + dp[j][i]);
}
}
printf("%d\n", f[n]);
}
return 0;
}