hdu 2476 String painter

来源:互联网 发布:苏黎世大学留学 知乎 编辑:程序博客网 时间:2024/06/05 19:19

题目链接

分析:
区间dp。开状态dp[l][r][c],表示[l, r]这个区间里染成c颜色的最少操作数。
考虑一段区间,我们从l开始染。枚举子区间[l, k],这段贪心地想,一定是染成和l的目标颜色一样才最优。然后把问题分解成两个子区间的问题就能解决了。如果区间中存在一段和目标一样的序列,那么这一段不需要染色,直接逃过。
dp[l][r][c]=min(dp[l+1][k][c[l]]+dp[k+1][r][c]+1)

代码:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cstdlib>#include <vector>#include <queue>#include <stack>using namespace std;const int maxn = 105;int dp[maxn][maxn][30];char a[maxn], b[maxn];int dfs(int l, int r, int c) {    if (l > r) return 0;    if (l == r) {        int t = c + 'a' - 1;        if (c == 27) t = a[l];        if (t == b[l]) return 0;        else return 1;    }    if (dp[l][r][c] != -1) return dp[l][r][c];    int s = l;    while (s <= r) {        int t = c + 'a' - 1;        if (c == 27) t = a[s];        if (t == b[s]) s ++;        else break;    }    if (s > r) return 0;    int tmp = 0x3f3f3f3f;    for (int k = s; k <= r; k ++)        tmp = min(tmp, dfs(s + 1, k, b[s] - 'a' + 1) + dfs(k + 1, r, c) + 1);    return dp[l][r][c] = tmp;}int main(int argc, char const *argv[]) {    while (~scanf("%s", a)) {        scanf("%s", b);        memset(dp, -1, sizeof(dp));        long len = strlen(a);        int ans = dfs(0, (int)len - 1, 27);        cout<<ans<<endl;    }}
0 0