String painter

String painter

标签: 区间DP


题目描述

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 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.

输出格式

A single line contains one integer representing the answer.

样例

Sample Input
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd

Sample Output
6
7

题解

一句话概括题目:每次可以选择一段区间涂色,问将一段颜色序列变成另一颜色序列最少多少次。
首先来思考一个简单版本:假设所有位置对应颜色都不同。(比如初始颜色序列为空白)
考虑涂色的性质,如果在最终序列中两个位置颜色相同,s[i]==s[j],则我们在染j的时候可以顺便把i也染色了。即可以考虑逐次转移法:
f[i,j]表示将[i,j]颜色完全不同染成最终相同颜色的最少次数。
由[i+1,j]推到[i,j],不过我们要判断[i+1,j]中是否有颜色与s[i]相等,因此还要再[i+1,j]中枚举断点:

f[i][j] = f[i + 1][j] + 1; //假设没有相等的,如果有的话下面也会取min值
for(int m = i + 1; m <= j; m ++)
    if(s[m] == s[i]) f[i][j] = min(f[i][j], f[i + 1][m] + f[m + 1][j]);

接着考虑初始序列可能与最终序列某些位置相同的情况,我们假设f[1,i]表示[1,i]将初始序列染成最终序列颜色的最少次数
如果s1[i]==s2[i],则f[1][i]=f[1][i-1],因为不需要染色了,否则枚举断点:

if(s[i] == s2[i]) f[1][i] = f[1][i - 1];
else
{
    for(int j = 1; j < i; j ++)
        f[1][i] = min(f[1][i], f[1][j] + f[j + 1][i]);
}

代码

#include<bits/stdc++.h>
#define N 110
using namespace std;

int cnt;
int a[N], f[N][N];
char s[N], s2[N];

int main()
{
    while(scanf("%s", s2 + 1) != EOF)
    {
        scanf("%s", s + 1);
        int len = strlen(s + 1); cnt = 0;
        for(int i = 1; i <= len; i ++)
            for(int j = i + 1; j <= len; j ++)
                f[i][j] = 1e9;
        for(int i = 1; i <= len; i ++)
            f[i][i] = 1;
        for(int k = 2; k <= len; k ++)
            for(int i = 1; i <= len - k + 1; i ++)
            {
                int j = k + i - 1;
                f[i][j] = f[i + 1][j] + 1;
                for(int m = i + 1; m <= j; m ++)
                    if(s[m] == s[i]) f[i][j] = min(f[i][j], f[i + 1][m] + f[m + 1][j]);
            }
        int tmp = 0;
        for(int i = 1; i <= len; i ++)
        {
            if(s[i] == s2[i]) f[1][i] = f[1][i - 1], tmp = i;
            else
            {
                for(int j = 1; j < i; j ++)
                    f[1][i] = min(f[1][i], f[1][j] + f[j + 1][i]);
            }
        }
        printf("%d\n", f[1][len]);
    }
    return 0;
} 

  转载请注明: iSecloud's Blog String painter

 上一篇
[HAOI2008]玩具取名 [HAOI2008]玩具取名
[HAOI2008]玩具取名标签:动态规划 区间DP 题目描述某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使
2019-05-20
下一篇 
Palindrome subsequence Palindrome subsequence
HDU4632 Palindrome subsequence标签: 区间DP 容斥原理 题目描述In mathematics, a subsequence is a sequence that can be derived from an
2019-05-20