zoukankan      html  css  js  c++  java
  • trie上记忆化搜索,括号匹配——cf1152D好题!

    一开始以为是卡特兰数的性质,,后来发现其实是dp,但是用记忆化搜索感觉更方便一点
    先来考虑字典树上的问题 设要求的序列长度是2n,我们用二元组(a,b)来表示前面长为a的序列中出现的 '(' - ')' = b 那么可以得知所有的符合这种要求的前缀的后缀形成的trie都是相同的 那么我们用二元组(i,j)来表示长为i的后缀中 ')' - '(' = j 只要这样一棵trie的最大匹配,就可以推出i+1的最大匹配 用dp[i][j]表示子树是二元组(i,j)对应的trie的最大匹配数 然后再来看最大匹配的问题: 每个结点只能选择一个子节点进行匹配,并且这个子节点不能再和下面一层匹配了 那么从底层往上考虑,2n层肯定没有匹配,2n-1层选一个叶子节点匹配,那么2n-2就没有匹配了 依次类推,可以发现奇数层的结点可以选一个子节点进行匹配,偶数层就没有匹配了 所以状态转移方程是: 因为是倒序往上的,dp[i][j]=dp[i-1][j+1]+dp[i-1][j-1]+(i%2==0)*flag,flag是子树个数

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2005
    #define ll long long 
    #define mod 1000000007
    ll n,dp[maxn][maxn];
    int dfs(int i,int j){
        if(dp[i][j]!=-1)return dp[i][j];
        if(i==0){//长度为0时,差值也要为0 
            if(j==0)return dp[i][j]=0;
            else return dp[i][j]=-2;    
        }
        if(i<j || j<0)return dp[i][j]=-2;
        int flag=0;
        ll res1=dfs(i-1,j+1),res2=dfs(i-1,j-1);
        if(res1>=0)flag++;else res1=0;
        if(res2>=0)flag++;else res2=0;
        
        dp[i][j]=(res1+res2+(i%2==0)*flag)%mod;
        if(flag)return dp[i][j];
        return dp[i][j]=-2;
    }
    int main(){
        cin>>n;
        memset(dp,-1,sizeof dp);
        cout<<dfs(2*n,0)<<endl;
        //    cout<<dp[5][1]<<endl;
    }
    View Code
     
  • 相关阅读:
    SpringCloud学习笔记(5)——Config
    SpringCloud学习笔记(4)——Zuul
    SpringCloud学习笔记(3)——Hystrix
    SpringCloud学习笔记(2)——Ribbon
    SpringCloud学习笔记(1)——Eureka
    SpringCloud学习笔记——Eureka高可用
    Eureka介绍
    微服务网关 Spring Cloud Gateway
    Spring Boot 参数校验
    Spring Boot Kafka
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10768732.html
Copyright © 2011-2022 走看看