涉及到两个过程,先是要计算出把一个空串转换成b串的最小花费
dp[i][j] = min ( dp[i][j-1] + 1 , dp[i][k] + dp[k+1][j](b[j]==b[k] );
第一种情况就是前面涂好的情况下直接对j刷字符
第二种情况就是当j和k处的字符相等时,那么我们可以将k到j刷一遍,那么花费就是k之前的刷一遍的代价和k+1到j-1之间刷一遍的代价之和,因为j处和k处是同时被刷,所以k在前一段区间被刷的同时可将j刷上,之后再刷之间的部分
接下来就是将a串转化为b串,转化的过程呢就是如果当前位置的字符和b串相等,那么最小花费不变,如果不相等,那么就可以从前面的某一位开始,刷上这种颜色,然后当作空串再进行处理,因为每次当前都作为最后一位,所以扫描到最后一位时不重不漏
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 107
using namespace std;
int dp[MAX][MAX];
char a[MAX];
char b[MAX];
int ans[MAX];
int main ()
{
while ( ~scanf ( "%s" , a+1 ) )
{
scanf ( "%s" , b+1 );
int n = strlen ( a+1 );
memset ( dp , 0 , sizeof ( dp ) );
for ( int i = 1; i <= n ; i++ )
dp[i][i] = 1;
for ( int i = 1 ; i < n ; i++ )
for ( int j = 1 ; j <= n-i ; j++ )
{
dp[j][j+i] = dp[j][j+i-1] + 1;
for ( int k = j ; k < j+i ; k++ )
if ( b[j+i] == b[k] )
dp[j][j+i] = min ( dp[j][j+i] , dp[j][k] + dp[k+1][j+i-1] );
/*if ( a[k] == b[k] )
{
int temp = 0;
if ( k-1>=j ) temp += dp[j][k-1];
if ( k+1<=i+j ) temp += dp[k+1][i+j];
// if (j == 0 && i+j == n-1 ) cout << "No : " << temp << endl;
dp[j][j+i] = min ( dp[j][j+i] , temp );
}*/
}
for ( int i = 1 ; i <= n ; i++ )
ans[i] = dp[1][i];
for ( int i = 1 ; i <= n ; i++ )
{
if ( a[i] == b[i] )
ans[i] = ans[i-1];
else
for ( int j = 1 ; j < i ; j++ )
ans[i] = min ( ans[i] , ans[j] + dp[j+1][i] );
}
printf ( "%d\n" , ans[n] );
}
}