zoukankan      html  css  js  c++  java
  • poj 3356 AGTC(线性dp)

    题目链接:http://poj.org/problem?id=3356

    思路分析:题目为经典的编辑距离问题,其实质为动态规划问题;

    编辑距离问题定义:给定一个字符串source,可以对其进行复制,替换,删除,增加操作,另外根据具体情况已经规定了每种操作的cost,现在要求求出一个操作序列,使其变为一个给定的字符串dest,并且该操作序列的cost的和最小(在该题目中复制开销为0,其他开销为1);

    该问题为动态规划问题,先对该问题进行分析:

    1)发掘最优子结构:

    假设源字符串为S[0, 1, 2,..,n-1],其长度为n,目标字符串为D[0, 1, 2, ...., m-1],长度为m,则该问题转换为求一个cost最小的操作序列将

    S[0,1,2,...,n-1]转换为D[0, 1, 2, ...., m-1];先考虑如何将S[0]转换为D[0];为了将S[0]转换为D[0],我们先选择一个操作,假设该操作是产生最

    优的操作序列的第一个操作,这样我们就能将S[0]转换为D[0],则原来的问题在该操作后产生了一个子问题(在不同的动态规划问题中可能会产

    生不同的子问题个数),即求一个cost最小的操作序列将S[1, 2, ... , n-1]转换为D[1, 2, ..., m-1],我们可以证明该子问题的最优解可以构造出原

    来问题的最优解,这样我们就发现了该问题的最优子结构;另外,我们还需要考虑第一步的选择有多少种(不同动态规划问题的选择的可能性的

    种类数目不同),即将S[0]转换为D[0]可以有多少种操作方法,明显在这个问题中有4种;

    2)重叠子问题

    如果该问题的递归算法反复地求解子问题,那么我们就称该最优化问题具有重叠子问题性质;在分治算法中,递归算法会生成全新的子问题,

    子问题与子问题之间是无关的;而动态规划算法不同,如求斐波那契数列的递归算法中求数列f[n]需要求解f[n-1]与f[n-2],而f[n-1]=f[n-2]+f[n-3],

    可以看到,在求斐波那契数列的递归算法中f[n-2]被求解多次,则求具有重叠子问题的结构,但是求斐波那契数列算法不是动态规划算法,因为其

    不具有最优子结构,这里提出该问题是让大家对重叠子问题有一个具体的认识;现在,我们可以明显看到,在求解编辑距离问题中,我们做出一次

    选择,就会产生一个子问题,因为在每一步中我们可能会做出多个选择,所以会求解多个相同的子问题,如在第一步中,我们可以选择复制(如果

    S[0]==D[0]),删除,替换,增加操作,每个选择的操作就会产生相同的子问题,即求解S[1,2, .., m]转换D[1, 2, ..., n]的最小的cost的操作序列;

    所以该问题具有重叠子问题;

    3)解法:

    对于该问题,我们刻画该问题的问题空间:假设dp[i][j]表示从字符串S[i, i+1, i+2, ...., m-1]转换为字符串D[j, j+1, j+2, ...., n-1]的操作序列的最小的cost和,

    则原问题为求dp[0][0];

    对于特殊的情况:

    dp[i, n] = m-i,表示使S[i, i+1, ...,m-1]转换为空字符串,只能删除m-i个字符,所以最小的cost和为m-i;

    dp[m, j] = n-j,表示使空字符串转换为D[j, j+1, ..., n-1],则只能增加n-j个字符,所以最小的cost和为n-j;

    关于选择的可能:

    <1>复制:dp[i, j] = dp[i+1, j+1], 如果S[i]==D[j],可以使用复制操作;

    <2>删除:dp[i, j] = dp[i+1, j] + 1,删除操作cost为1,删除S[i],子问题为dp[i+1, j];

    <3>替换:dp[i, j] = dp[i+1, j+1] + 1,替换操作只能在S[i]与D[j]不相等时才能选择;

    <4>增加:dp[i, j] = dp[i, j+1] + 1,同样的,增加操作cost为1;

    则该问题的动态规划方程已经给出,可以求解该问题;

    代码如下:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int MAX_N = 1000 + 10;
    char source[MAX_N], dest[MAX_N];
    int dp[MAX_N][MAX_N];
    
    inline int Min(int a, int b) { return a > b ? b : a; }
    
    int main()
    {
        int s_len, d_len;
    
        while(scanf("%d %s", &s_len, source) != EOF)
        {
            scanf("%d %s", &d_len, dest);
    
            memset(dp, 0, sizeof(dp));
            for (int i = 0; i <= d_len; ++i)
                dp[s_len][i] = d_len - i;
            for (int i = 0; i <= s_len; ++i)
                dp[i][d_len] = s_len - i;
            for (int i = s_len - 1; i >= 0; --i)
            {
                for (int j = d_len - 1; j >= 0; --j)
                {
                    int min_cost = 100000;
    
                    min_cost = Min(min_cost, dp[i + 1][j] + 1);
                    min_cost = Min(min_cost, dp[i][j + 1] + 1);
                    if (source[i] == dest[j])
                        min_cost = Min(min_cost, dp[i + 1][j + 1]);
                    else
                        min_cost = Min(min_cost, dp[i + 1][j + 1] + 1);
                    dp[i][j] = min_cost;
                }
            }
            printf("%d
    ", dp[0][0]);
        }
    
        return 0;
    }
  • 相关阅读:
    [kuangbin带你飞]专题十二 基础DP1 E
    hdu 1203 I NEED A OFFER! (01背包)
    hdu 2602 Bone Collector (01背包)
    hdu 4513 吉哥系列故事——完美队形II (manacher)
    hdu 2203 亲和串 (KMP)
    hdu 1686 Oulipo (KMP)
    hdu 1251 统计难题 (字典树)
    hdu 2846 Repository (字典树)
    hdu 1711 Number Sequence (KMP)
    poj 3461 Oulipo(KMP)
  • 原文地址:https://www.cnblogs.com/tallisHe/p/4521162.html
Copyright © 2011-2022 走看看