zoukankan      html  css  js  c++  java
  • lightoj 1013 dp

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1013

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    
    const int maxn = 35;
    const int INF  = 0x3f3f3f;
    
    int main()
    {
        //freopen("E:\acm\input.txt","r",stdin);
        int T;
        cin>>T;
        for(int t=1;t<=T;t++){
            long long dp1[maxn][maxn],dp2[maxn][maxn];     /**  dp1[i][j] = (i+j) - num(s1中前i个和s2中前j个的最长公共子序列)。
                                                                dp2[i][j]是包含s1中前i个和s2中前j个字母的最短字符串的个数。
                                                           **/
            char s1[maxn],s2[maxn];
            scanf("%s %s",s1+1,s2+1);
            int Len1 = strlen(s1+1), Len2 = strlen(s2+1);
    
            for(int i=0;i<=Len1;i++)   dp1[i][0] = i, dp2[i][0] = 1;
            for(int i=0;i<=Len2;i++)   dp1[0][i] = i, dp2[0][i] = 1;
    
            for(int i=1;i<=Len1;i++)
               for(int j=1;j<=Len2;j++){
                 if(s1[i] == s2[j]){
                       dp1[i][j] = dp1[i-1][j-1] + 1;
                       dp2[i][j] = dp2[i-1][j-1];  //这个时候直接把s1[i](s2[j])放在合成串s后面,所以加一;
                    }
                      else{
                        if(dp1[i-1][j] == dp1[i][j-1]){
                            dp1[i][j] = dp1[i-1][j] + 1;
                            dp2[i][j] = dp2[i-1][j] + dp2[i][j-1];   /**这个地方最难理解,dp1[i-1][j] == dp1[i][j-1] 得出s1[i-1] != s2[j] ,s1[i] != s2[j-1].
                                                                        dp2[i-1][j] 可以理解为把s1[i]放在合成串s的最后的方法数,dp2[i][j-1]可以理解为把s2[j]放在合成串s最后的方法数。
                                                                        加起来就的到总共的组合数
                                                                     **/
                        }
                        else if(dp1[i-1][j] > dp1[i][j-1]){  //1.说明s1[i]能与s2[j-1]或者j-1之前某个组合在一起,而s2[j]不能。
                            dp1[i][j] = dp1[i][j-1] + 1;     //取小的; 并添加了一个字母s2[j];
                            dp2[i][j] = dp2[i][j-1];         //由1.这句知道:s2[j]只能添加在合成串s的最后。
                        }
                        else{                                //此处分析同上。
                            dp1[i][j] = dp1[i-1][j] + 1;     //取小的; 并添加了一个字母s1[i];
                            dp2[i][j] = dp2[i-1][j];
                        }
                    }
            }
            printf("Case %d: %lld %lld
    ",t,dp1[Len1][Len2],dp2[Len1][Len2]);
        }
    }
    //总结下,这个dp1其实就是简单的LCS的变形,而dp2就是关键,这是参考别人的方法,只是觉得很精妙就学习下。
    View Code
  • 相关阅读:
    Ubuntu 18.04安装gcc、g++ 4.8
    Java 接口返回值集合防止空指针
    Linux CentOS7.9环境下搭建Java Web 环境
    Springboot集成UReport2
    linux 环境中 单独执行 python 脚本
    sql 注入的问题
    检验上传文件的大小
    Gunicorn使用讲解
    CentOS下安装部署对象存储服务MinIO
    阿里云CentOS7安装MySQL
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3273453.html
Copyright © 2011-2022 走看看