HDU 2476 String painter(区间dp)

题意: 给定两个字符串,让求最少的变化次数从第一个串变到第二个串

思路: 区间dp, 直接考虑两个串的话太困难,就只考虑第二个串,求从空白串变到第二个串的最小次数,dp[i][j] 表示i->j这个区间上的最优解,那么dp[i][j] = min(dp[i + 1][j], dp[i + 1][k] + dp[k + 1][j]),这个状态转移方程中是枚举k的位置,前提是第二个串的第i个字符必须和第k个字符相等,因为这样才是求的最优的,不然的话,就没必要刷到k这个位置了。到最后在枚举每个位置,看第一个串是否与第二个串的对应位置相等,找出最优解。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 110;
int dp[maxn][maxn], ans[maxn];
char a[maxn], b[maxn];
int main()
{
    while (~scanf("%s %s", a + 1, b + 1))
    {
        int len = strlen(a + 1);
        memset(dp, 0, sizeof(dp));
        for (int i = len; i >= 1; i--)
        {
            for (int j = i; j <= len; j++)
            {
                dp[i][j] = dp[i + 1][j] + 1;
                for (int k = i + 1; k <= j; k++)
                    if (b[i] == b[k])
                        dp[i][j] = min(dp[i][j], dp[i + 1][k] + dp[k + 1][j]);
            }
        }
        for (int i = 1; i <= len; i++)
            ans[i] = dp[1][i];
        for (int i = 1; i <= len; i++)
        {
            if (a[i] == b[i])
                ans[i] = ans[i - 1];
            else//如果不等的话,就枚举每一个位置,找出一个最小的来 
            {
                for (int j = 1; j < i; j++)
                    ans[i] = min(ans[i], ans[j] + dp[j + 1][i]);
            }
        }
        printf("%d\n", ans[len]);
    }
    return 0;
}
View Code

 

posted @ 2015-08-31 15:02  Howe_Young  阅读(204)  评论(0编辑  收藏  举报