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

来源:互联网 发布:淘宝网商贷款扣钱 编辑:程序博客网 时间:2024/06/10 18:52

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
zzzzzfzzzzzabcdefedcbaababababababcdcdcdcdcdcd
 

Sample Output
67
 

Source
2008 Asia Regional Chengdu
 

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 WINtypedef __int64 LL;#define iform "%I64d"#define oform "%I64d\n"#define oform1 "%I64d"#elsetypedef 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