题意:
长度都为n的字符串s1和s2,每次刷颜色可将一段区间内的字符染成相同的字符,问把s1刷成s2需要的最小次数。1 <= n <= 100。
题解:
1.dp[i][j]表示把空白字符串的[i , j]染成s2的[i , j]需要的最小次数。
2.初始化dp[i][i] 和 dp[i][i + 1]。
3.区间dp常把i看作特殊点,先认为i需要涂一下,dp[i][j] = dp[i + 1][j] + 1。然后遍历[i , j]内的断点,若s2[i] = s2[k],那么可以涂k的时候把i给涂掉。dp[i][j] = min(dp[i][j] , dp[i + 1][k] + dp[k + 1][j])。
4.因为s1的串和s2的串可能部分相同,会比空白字符串染成s2更快,初始化ans为dp[1]。ans[i]表示把s1的[1 , i]涂成s2的[1 , i]需要的最小次数。假如s1[i] = s2[i],则ans[i] = ans[i - 1]。若不同,则在[1,i)寻找断点,ans[i] = min(ans[i] , ans[j] + dp[j + 1][i])。
#include <bits/stdc++.h>
#define N 105
#define inf 0x3f3f3f3f
using namespace std;
int dp[N][N] ;
int ans[N] ;
int main()
{
char s1[N] , s2[N] ;
int len ;
int i , j , k , d ;
while(scanf("%s%s" , s1 + 1 , s2 + 1) != EOF)
{
len = strlen(s2 + 1);
for(i = 1 ; i <= len ; i ++)
dp[i][i] = 1 ;
for(i = 1 ; i <= len - 1 ; i ++)
dp[i][i + 1] = 1 + (s2[i] != s2[i + 1]) ;
for(d = 2 ; d <= len - 1 ; d ++)
for(i = 1 ; i + d <= len ; i ++)
{
j = i + d ;
dp[i][j] = dp[i + 1][j] + 1 ;
for(k = i + 1 ; k <= j ; k ++)
if(s2[i] == s2[k])
dp[i][j] = min(dp[i][j] , dp[i + 1][k] + dp[k + 1][j]) ;
}
for(i = 1 ; i <= len ; i ++)
ans[i] = dp[1][i] ;
ans[0] = 0 ;
for(i = 1 ; i <= len ; i ++)
if(s1[i] == s2[i])
ans[i] = ans[i - 1] ;
else
for(j = 1 ; j < i ; j ++)
ans[i] = min(ans[i] , ans[j] + dp[j + 1][i]) ;
printf("%d\n" , ans[len]) ;
}
}
.