zoukankan      html  css  js  c++  java
  • cf1272F——经典升维dp,好题!

    /*
    给两个括号序列,用一个合法的括号串来覆盖这两个串,求出这个最短串
    这个问题可以分解成两个条件:
        1.用一个最短的括号序列来覆盖这两个串 
        2.这个序列要合法
    首先考虑第一个条件:
        不难想到用两个状态dp[i,j]来表示匹配s[1..i],t[1..j]时的最短长度
         转移也很简单:初始状态dp[0,0]=0,后面加'(',后面加')':都分别取更新对应状态  
        最后的结果是dp[lens,lent] 
    
    然后再来考虑上第二个条件
        括号序列合法的条件是所有的前缀和>=0,且最后的和是0(懂我意思吧)
        要让最后的串满足这个条件,我们必须在转移时考虑到前缀和状态,这个状态>=0,
        自然想到升一维dp,dp[i,j,k]来表示匹配到s[1..i],t[1..j]且前缀和是k的最短长度
        初始状态dp[0,0,0]=0,转移同上 
        这个前缀和的范围必定在[0,lens+lent],所以整个dp的复杂度是O(n^3) 
    最后的答案:
        dp[i,j,k]+k里找个最小的记为mink 
    由于要输出解法,所以我们记下前驱即可(这都是细枝末节的实现了) 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 1005
    
    char s[N],t[N];
    int dp[205][205][405],lens,lent; 
    struct Node{
        int i,j,k,flag,len;
        Node(){}
        Node(int i,int j,int k,int flag,int len):i(i),j(j),k(k),flag(flag),len(len){}
    }pre[205][205][405];
    
    stack<char>stk;
    void print(Node node){
        if(node.flag==-1)stk.push(')');
        else if(node.flag==1)stk.push('(');
        if(node.len)
            print(pre[node.i][node.j][node.k]);
    }
    
    int main(){
        scanf("%s%s",s+1,t+1);
        lens=strlen(s+1);lent=strlen(t+1);
        
        memset(dp,0x3f,sizeof dp);
        dp[0][0][0]=0;
        
        for(int i=0;i<=lens;i++)
            for(int j=0;j<=lent;j++)
                for(int k=0;k<=lens+lent;k++){
                    if(dp[i][j][k]==0x3f3f3f3f)continue;
                    if(k){//加个右括号 
                        int f1,f2;
                        if(s[i+1]==')')f1=1;
                        else f1=0;
                        if(t[j+1]==')')f2=1;
                        else f2=0;
                        if(dp[i][j][k]+1<dp[i+f1][j+f2][k-1]){//更新状态 
                            Node node=Node(i,j,k,-1,dp[i][j][k]);
                            pre[i+f1][j+f2][k-1]=node;
                            dp[i+f1][j+f2][k-1]=dp[i][j][k]+1;                 
                        } 
                    }
                    //加个左括号
                    int f1,f2;
                    if(s[i+1]=='(')f1=1;
                    else f1=0;
                    if(t[j+1]=='(')f2=1;
                    else f2=0;
                    if(dp[i][j][k]+1<dp[i+f1][j+f2][k+1]){//更新状态 
                        Node node=Node(i,j,k,1,dp[i][j][k]);
                        pre[i+f1][j+f2][k+1]=node;
                        dp[i+f1][j+f2][k+1]=dp[i][j][k]+1;                 
                    } 
                }
        
        int Min=0x3f3f3f3f,mink=0;
        for(int k=1;k<=lens+lent;k++){
            if(dp[lens][lent][k]+k<dp[lens][lent][mink]+mink){
                mink=k;
            }
        } 
        
        for(int i=1;i<=mink;i++)stk.push(')');    
        print(pre[lens][lent][mink]);
        while(stk.size()){
            cout<<stk.top();
            stk.pop();
        }
        puts("");
    }
  • 相关阅读:
    Docker学习笔记04---网络部分
    Docker学习笔记03---DockerFile
    sqlmap使用手册
    windows系统应急响应排查手册
    linux系统应急响应排查手册
    Sublime Text中输入python代码,不能执行问题解决
    人工智能“理解”话语了吗 ——《我们赖以生存的意义》读书笔记(下)
    人工智能“理解”话语了吗 ——《我们赖以生存的意义》读书笔记(上)
    常识推理和NLI(natural language inference)
    常识推理和组合泛化 (commonsense & compositionality)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12113735.html
Copyright © 2011-2022 走看看