String painter_区间DP

Time Limit : 5000/2000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 15   Accepted Submission(s) : 10

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

Problem 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

zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd

Sample Output

6
7

题目看了很久没看懂,真为我的智商捉急!!

题意:

给出两个串s1和s2,一次只能将一个区间刷一次,问最少几次能让s1=s2

例如zzzzzfzzzzz,长度为11,我们就将下标看做0~10

先将0~10刷一次,变成aaaaaaaaaaa

1~9刷一次,abbbbbbbbba

2~8:abcccccccba

3~7:abcdddddcba

4~6:abcdeeedcab

5:abcdefedcab

这样就6次,变成了s2串了

先求出空字符串变为目标字符串的最小次数。然后在进行讨论。

初始串与目标串本来已经匹配的地方就无须再覆盖。
#include<iostream>
#include<string>
#include<string.h>
using namespace std;
const int inf=0x7777777;
int dp[500][500],a[500];//dp记录空白串到s2的最小次数
int main()
{
    string s1,s2;
    while(cin>>s1>>s2)
    {
        int len=s1.length();
        s1=" "+s1;
        s2=" "+s2;
        memset(dp,0,sizeof(dp));
        for(int j=1;j<=len;j++)
        {
            for(int i=j;i>=1;i--)//i是头,j是尾;
            {
                dp[i][j]=dp[i+1][j]+1;//先记录为最坏的状态,即每个都刷;
                for(int k=i+1;k<=j;k++)//遍历i+1和j之间所有刷法;
                {
                    if(s2[i]==s2[k])
                        dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);//寻找i到j中最优的k;
                }
            }
        }
        for(int i=1;i<=len;i++) a[i]=dp[1][i];//将从1到i的最小次数初始化a;
        for(int i=1;i<=len;i++)
        {
            if(s1[i]==s2[i]) a[i]=a[i-1];//对应位置相等则可以不用刷
            else
            {
                for(int j=0;j<i;j++)
                    a[i]=min(a[i],a[j]+dp[j+1][i]);//寻找j来分割区间得到最优解  
            }

        }
          cout<<a[len]<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/iwantstrong/p/5751134.html