HDU 2476 String painter (区间DP)

hdu 2476

题目:

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

题意:输入两个长度相等的字符串A, B, 对A串进行操作使其变成B串, 每次可对A串的某一段就行操作将其变成同一字符, 求变成B串的最小操作次数。

题解:还是很容易想到区间DP的, 对每段的更改操作就是对区间的操作, 直接对A的操作是很难想的, 不如dp[i][j]直接求一个空串变成B串的最小次数, 有了dp值之后再用ans[i]记录下0 ~ i的初始串到目标串的更改次数, ans[i]枚举出所有情况即可。

dp[i][j] = dp[i + 1][j] + (str2[i] == str2[j] ? 0 : 1)为初始化条件, 当i j相等时dp值是1.

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    int i, j, n ,ans[105], len, k;
    int dp[105][105];
    char str1[105], str2[105];
    while(~scanf("%s%s", str1, str2)){
        n = strlen(str1);
        for(len = 1;len <= n;len++){//区间长度
            for(i = 0;i < n - len + 1;i++){//区间起点
                j = len + i - 1;//区间终点
                if(len == 1)
                    dp[i][i] = 1;//单一点初始化为1
                else dp[i][j] = dp[i + 1][j] + (str2[i] == str2[j] ? 0 : 1);//相同时可以一同改掉,不同时次数++
                for(k = i + 1;k < j;k++)//枚举分割点
                    if(str2[i] == str2[k])//字符相同时进行状态转移
                        dp[i][j] = min(dp[i][j], dp[i + 1][k] + dp[k + 1][j]);
            }
        }
        for(i = 0;i < n;i++){
            ans[i] = dp[0][i];//初始化ans[i]
            if(str1[i] == str2[i])
                ans[i] = ans[i - 1];//字符相同是可以不转化
            for(j = 0;j < i;j++)
                ans[i] = min(ans[i], ans[j] + dp[j + 1][i]);//枚举所有情况找最小值
        }
        printf("%d\n", ans[n - 1]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LxcXingC/article/details/81562933