hdu2476(区间dp)

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[i][j]来说的话如何求呢?显然 dp[i][j]要由dp[i][k]+dp[k+1][j]决定,如果s2[i]==s2[k]则dp[i][j]=dp[i+1][k]+dp[k+1][j],但有一种情况要考虑的是如果所有s2[i]!=s2[k],怎么办?!所以dp[i][j]的初值不能赋值为正无穷,区间dp很常见的方法就是以区间i到j为对象,取i为特殊点作为参照,所以dp[i][j]最常见复制方式(就是最大值(题目要求的是最小值所以我们考虑最大值))就是dp[i][j]=dp[i+1][j]+1;这样代码实现起来应该没问题了,递推和记忆化搜索都行。

第二步在开个数组记录前i个字母要改变的最小值,那么怎样最小呢?看代码就懂了!

#include<iostream>
#include<algorithm>
#include <cstdio>
#include <cmath>
#include<cstring>
using namespace std;
int a[105],dp[105][105];char s1[105],s2[105];
int solve(int i,int j)
{
    if(dp[i][j]!=-1)return dp[i][j];
    if(i>j)return dp[i][j]=0;
    if(i==j)return dp[i][j]=1;
    dp[i][j]=solve(i+1,j)+1;
    for(int k=i+1;k<=j;k++)
    if(s2[k]==s2[i])
    dp[i][j]=min(solve(i+1,k)+solve(k+1,j),dp[i][j]);
    return dp[i][j];
}

int main ()
{
    while(cin>>s1>>s2)
    {
        memset(dp,-1,sizeof(dp));memset(a,0,sizeof(a));
        int l=strlen(s1);
        for(int i=0;i<l;i++)
        {
            for(int j=i;j<l;j++)
            int t=solve(i,j);
        }
      //  cout<<dp[0][0]<<endl;
        for(int i=0;i<l;i++)
        {
            a[i]=dp[0][i];
            if(s1[i]==s2[i])
                {
                    if(i==0)
                        a[i]=0;
                    else
                    a[i]=a[i-1];
                }
            else
            {
                for(int j=0;j<i;j++)
                    a[i]=min(a[i],a[j]+dp[j+1][i]);
            }
        }
        printf("%d\n",a[l-1]);
    }
    return 0;
}


posted @ 2015-05-24 17:01  martinue  阅读(152)  评论(0编辑  收藏  举报