HDU-2476-String painter(区间DP+DP)

String painter

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

解题思路:

还是一道区间DP。不过有点难,想了很久没想出来最后是看了别人的题解才写出来。
直接DP写不出来。用一点技巧,先用一个空串刷成目标串,区间DP计算最优解。
转移方程:

dp[j][ends] = min(dp[j+1][ends],dp[j][ends-1])+1;
for(int k = j+1 ; k <= ends; k ++)
{
    if(s2[k] == s2[j])	// s[j]与s[k]相同 可以dp[j][k]和dp[j+1][k]等价
        dp[j][ends] = min(dp[j][ends],dp[j+1][k]+dp[k+1][ends]);
}

然后再进行一次DP求解答案。可以想到如果当前位置两个串的值相等那么res[i]和res[i-1]是等价的,因为当前点可以不刷。然后再枚举一遍分割点
转移方程:

if(s1[i] == s2[i])
    res[i] = res[i-1];
else
{
    for(int j = 0; j < i; j ++)
        res[i] = min(res[i],res[j]+dp[j+1][i]);
}

AC代码:

//#include <bits/stdc++.h>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <cstring>
#include <utility>
#include <string>
#define INF 0xfffffff
#define int long long

using namespace std;
const int mod = 1e4+7;
const int N = 1e2+10;
int res[N];
int dp[N][N];

signed main()
{
    string s1,s2;
    while(cin>>s1>>s2)
    {
        int sz = s1.size();
        memset(dp,0,sizeof(dp));
        memset(res,0,sizeof(res));
        for(int i = 1 ; i <= sz ; i++)
        {
            for(int j = 0 ; j <= sz+1-i ; j ++)
            {
                int ends = j+i-1;
                dp[j][ends] = min(dp[j+1][ends],dp[j][ends-1])+1;
                for(int k = j+1 ; k <= ends; k ++)
                {
                    if(s2[k] == s2[j])
                        dp[j][ends] = min(dp[j][ends],dp[j+1][k]+dp[k+1][ends]);
                }
            }
        }
        for(int i = 0; i < sz; i ++)
            res[i] = dp[0][i];
        for(int i = 0 ; i < sz ; i++)
        {
            if(s1[i] == s2[i])
                res[i] = res[i-1];
            else
            {
                for(int j = 0; j < i; j ++)
                    res[i] = min(res[i],res[j]+dp[j+1][i]);
            }
        }
        cout<<res[sz-1]<<endl;
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值