zoukankan      html  css  js  c++  java
  • 习题9-6 uva 10723

    题意:

    给你两个字符串,求一个最短的串,使得输入的两个串均是他的子序列(不一定连续)

    思路:

    可以看出ans = 两个串的长度和 - 两个串的最长公共子序列,在最后的构造处GG。 
    在构造时想了很久,想复杂了- -,后来看别人思路完全可以根据最长公告子序列的原理来

    而且下次可以考虑画个图来看


    ①a[i] == b[j]说明ans[i][j]只需要在ans[i-1][j-1]的组合基础上加一个字母a[i](b[j]),所以ans[i][j] = ans[i-1][j-1]
    ②不相等时
    dp[i][j]  =  max(dp[i-1][j],dp[i][j-1])
    1.假设dp[i][j-1] > dp[i-1][j]
    说明ans[i][j]需要在ans[i][j-1]的组合基础上加一个字母b[j],所以ans[i][j] = ans[i][j-1]
    2.dp[i-1][j] > dp[i][j-1] 的原理同上
    3.如果dp[i][j-1] == dp[i-1][j],则说明我们两种都选,ans[i][j-1]的组合基础上加一个字母b[j] 
    或者 ans[i-1][j]的组合基础上加一个字母a[i],所以ans[i][j] = ans[i][j-1] + ans[i-1][j];


    感觉对动归的理解不到位- -,Wo好弱


    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const int maxn= 50;
    char a[maxn];
    char b[maxn];
    int dp[maxn][maxn];
    ll tans[maxn][maxn];
    
    int main()
    {
        int n;
        scanf("%d",&n);
        getchar();
        int cas = 1;
        while(n--)
        {
    
            gets(a+1);
            gets(b+1);
            int lena = strlen(a+1);
            int lenb = strlen(b+1);
            memset(dp,0,sizeof(dp));
            for(int i = 0; i <= lena; i++)
                tans[i][0] = 1;
            for(int j =0; j <= lenb; j++)
                tans[0][j] = 1;
            for(int i = 1; i <= lena; i++)
                for(int j = 1; j <= lenb; j++)
                {
                    if(a[i] == b[j])    //相等则只需在后面加上字母
                    {
                        dp[i][j] = dp[i-1][j-1] + 1;
                        tans[i][j] = tans[i-1][j-1];
                    }
                    else if(dp[i][j-1] > dp[i-1][j])
                    {
                        dp[i][j] =dp[i][j-1];
                        tans[i][j] = tans[i][j-1];
                    }
                    else if(dp[i-1][j] > dp[i][j-1])
                    {
                        dp[i][j] =dp[i-1][j];
                        tans[i][j] = tans[i-1][j];
                    }
                    else
                    {
                        dp[i][j] =dp[i][j-1];
                        tans[i][j] = tans[i][j-1] + tans[i-1][j];
                    }
                }
            int ans =lena+lenb-dp[lena][lenb];
            printf("Case #%d: %d %lld
    ",cas++,ans,tans[lena][lenb]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    ObjectARX 学习笔记007:创建模态对话框的一般步骤
    c#的DateTime.Now函数详解
    LinQ 使用案例1
    LinQ 泛型方法Array>ForEach在数组中进行迭代并调用自定义的委托
    LinQ Lambda表达式用作泛型活动
    win7x64bit VS2010 CAD2013断点 调试 捕捉成功,困扰一周的问题解决了
    法兰数据库设计方案
    关于CAD的开发思路
    法兰程序CAD开发的进展
    法兰动态块设计思路
  • 原文地址:https://www.cnblogs.com/Przz/p/5409680.html
Copyright © 2011-2022 走看看