String painter hdu2476(区间dp)

点击打开链接

String painter

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4451    Accepted Submission(s): 2079


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

讲道理,一开始题目都没看懂,以为是一个一个的改变字母。。。真的是被自己蠢到了。根据样例才看懂原来一次性可以改变多个

题意:给出两个字符串ch1和ch2,一次操作能将ch1的一段字符串改变成同一个字符,求把ch1改变成ch2所需要的最少操作数?

今天做这道题的历程就是,好不容易搞懂题意,然后又不知道该怎么做了……看了半天想到是区间dp,刷串的时候,被刷的串的第一个字符和最后一个字符必须相同,不然就是没有意义的(理解一下),但是怎么从ch1变成ch2呢?又没有思路了。。。纠结了半天去找了一下题解,这道题的解题方法真的是贼机智,首先把一个空串变成字符串ch2,

用dp[i][j]记录从空串变成ch2,然后再考虑从串ch1变成ch2,具体还是看代码吧,感觉自己语言表达能力太弱了。。。


#include<iostream>
#include<stdio.h>
#include<string>
#include<math.h>
#include<queue>
#include<vector>
#include<string.h>
#include<iterator>
using namespace std;
typedef unsigned long long ll;

int main()
{
    char ch1[105] , ch2[105];
    int dp[105][105];
    int ans[105];
    while(~scanf("%s" , ch1)){
        scanf("%s" , ch2);
        int n = strlen(ch1);
        //cout<<ch1<<endl<<ch2<<endl;
        //cout<<n<<endl;
        memset(dp , 0 , sizeof(dp));
        for(int i = 0 ; i <= n ; i ++)
            dp[i][i] = 1;
        for(int len = 1 ; len < n ; len ++){//循环区间长度
            for(int i = 0 ; i < n - len ; i ++){//枚举起点
                int j = i + len ;//终点
                dp[i][j] = dp[i + 1][j] + (ch2[i] == ch2[j]?0 : 1 );//初始化,起点与终点相同才有必要刷串
                for(int k = i + 1 ; k < j ; k ++){//枚举中间点
                    if(ch2[i] == ch2[k])
                        dp[i][j] = min(dp[i][j] , dp[i + 1][k] + dp[k+1][j]);
                }
            }
        }
        //cout<<dp[0][n-1]<<"..."<<endl;
        for(int i = 0 ; i < n ; i ++){
            ans[i] = dp[0][i];
            if(ch1[i] == ch2[i])//相同的话就没必要刷
                ans[i] = ans[i - 1];
            for(int j = 0 ; j < i ; j ++){
                ans[i] = min(ans[i] , ans[j] + dp[j + 1][i]);
            }
        }
        cout<<ans[n-1]<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值