String painter (hdu 2476)

来源:互联网 发布:淘宝的一个差评 编辑:程序博客网 时间:2024/05/16 15:44

F - String painter
Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status Practice HDU 2476
Appoint description: 

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

zzzzzfzzzzzabcdefedcbaababababababcdcdcdcdcdcd
 

Sample Output

67



题意:

给出两个字符串s1,s2。对于每次操作可以将 s1 串中的任意一个子段变成另一个字符。问最少需要多少步操作能将s1串变为s2串。


思路:

首先我们应该关心的是s2串是怎么由一个空串变来的,我们先认为s1和s2任何一个字符都不相等,那么用dp[i][j]来表示要变成s2串 i~j 所需要的最少操作步数。


如果不考虑颜色重复利用的情况(例如  aba  应该先变成 aaa 再变成 aba 只消耗两步),那么考虑第 i 个元素,一定是有 dp[i][j] = dp[i+1][j] + 1; 


如果考虑在区间 i~j 中可能会有 元素 k 与 元素 i 相同,即 i 或许能和其他元素一起变,那么区间 i ~ j 就被拆成 i~k 和 k+1 ~ j ,因为元素 i 可以和元素 k 共用,所以计算时有  dp[i][j] = min(dp[i][j],dp[i+1][k] + dp[k+1][j]);



在得到了一个s2串的相关dp数组后,我们考虑s1串,如果s1串和s2串在某一个点相等了,即表示这一点可以不用特意去刷一次,那么便可以由这一点来分成两个区间。


如果用 ans[i]来记录0~i这个区间的最终答案,那么我们需要将其初始化为 ans[i] = dp[0][i];(假设s1串与s2串完全不同)。


如果发现了s1[i] == s2[i],那么显然有 ans[i] = min(ans[i],ans[i-1]); (因为这一点其实可以不刷)


如果不相等,我们也可以在前i个元素中寻找一个断点来将答案优化。(因为一个大区间的最优解可能由两个小区间的最优解组成)。即

ans[i] = min(ans[i],ans[j] + dp[j+1][i]);


#include"iostream"#include"cstring"#include"cstdio"#include"algorithm"using namespace std;char s1[105];char s2[105];int dp[105][105];int ans[105];int main(void){    while(~scanf("%s%s",s1,s2))    {        int siz = strlen(s1);        memset(dp,0,sizeof(dp));        for(int i = 0;i < siz;i++) dp[i][i] = 1;        for(int j = 0;j < siz;j++)        {            for(int i = j - 1;i >= 0;i--)            {                dp[i][j] = dp[i+1][j] + 1;                for(int 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(int i = 0;i < siz;i++)            ans[i] = dp[0][i];                    if(s1[0] == s2[0]) ans[0] = 0;        for(int i = 1;i < siz;i++)        {            if(s2[i] == s1[i])                ans[i] = min(ans[i],ans[i-1]);            else            {                for(int j = 0;j < i;j++)                    ans[i] = min(ans[i],ans[j] + dp[j+1][i]);            }        }        printf("%d\n",ans[siz-1]);    }    return 0;}


0 0