HDU 2476 | UVALive 4394 - String painter (区间DP)

String painter

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1625    Accepted Submission(s): 728



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
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   2480  2481  2478  2482  2475 
 

Statistic |  Submit |  Discuss |  Note


题意:

给定两个长度相等的只由小写字母组成的字符串s、t,每步可以把一个连续字串刷成相同的字母,问至少需要多少步才能把s变成t。


思路:

想了好久 还是没想出来 

一开始的方法是 dp[i][j][k] 表示把S[i,j]刷为k,k=26表示不刷即保持原态,0-25就是刷为'a'+k,复杂度 O(n*n*27*n*27) = 7*10^8果断超时了 然后看题解T^T


先不考虑s,考虑一个空串刷为t需要多少步  这个挺巧妙的 想不到 弱。。

dp[i][j] 表示一个空串刷为t最少的步数 则


dp[i][j] = dp[i+1][j] + (strB[i] == strB[j] ? 0 : 1)  意思是把如果strB[i] == strB[j] ,则刷的时候直接把i..j都刷为相同的

这里要注意的是 dp[i][j] != dp[i-1][j-1] + (strB[i] == strB[j] ? 0 : 1)  因为比如是abba这个结果是0,写为dp[i+1][j]是为了保证中间的字母这两个端点刷的一致 这里是留下了右端点即j来保证


dp[i][j] = min(dp[i+1][k] + dp[k+1][j])(前提strB[i] == strB[k])

这里是留下了右端点即k来保证[i+1, k]这段区间和i、k刷的颜色相同,



#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 100 + 20;
char strA[maxn];
char strB[maxn];
int dp[maxn][maxn];
int f[maxn];


int main() {
    while(scanf("%s%s", strA, strB) != EOF) {
        int n = strlen(strA);
        memset(dp, 0, sizeof(dp));
        for(int len=1; len<=n; len++) {
            for(int s=0; s+len<=n; s++) {
                int e = s + len - 1;
                if(len == 1) {
                    dp[s][e] = 1;
                    continue;
                }
                dp[s][e] = dp[s+1][e] + (strB[s] == strB[e] ? 0 : 1);
                for(int j=s+1; j<=e; j++) {
                    if(strB[s] == strB[j]) dp[s][e] = min(dp[s][e], dp[s+1][j]+dp[j+1][e]);
                }
            }
        }
        f[0] = strA[0] != strB[0];
        for(int i=1; i<n; i++) {
            f[i] = dp[0][i];
            if(strA[i] == strB[i]) f[i] = min(f[i], f[i-1]);
            for(int j=0; j<i; j++) {
                f[i] = min(f[i], f[j]+dp[j+1][i]);
            }
        }
        int ans = f[n-1];
        printf("%d\n", ans);
    }

    return 0;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值