涉及到两个过程,先是要计算出把一个空串转换成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] );
    }
}