Codeforces Round #554 (Div. 2) D 贪心 + 记忆化搜索

https://codeforces.com/contest/1152/problem/D

题意

给你一个n代表合法括号序列的长度一半,一颗有所有合法括号序列构成的字典树上,选择最大的边集,边集的边没有公共点,问边集大小

题解

  • 对于一颗字典树,从低向上贪心,最底层的边全拿,定义好状态,记忆化搜索计数
  • 定义dp[i][j]为左括号数量为i,右括号数量为j的最大边集
    • \(i<n\),\(dp[i][j]->dfs(i+1,j)\)
    • \(j<i\),\(dp[i][j]->dfs(i,j+1)\)
  • 注意一下,相邻两层不能连续选边

代码

#include<bits/stdc++.h>
#define ll long long
#define P 1000000007
#define pii pair<ll,int>
#define mk make_pair
#define ft first
#define se second
using namespace std;
pii dp[1005][1005];
int n;

pii dfs(int i,int j){
    if(i==n&&j==n)return mk(0,0);
    pii &ans=dp[i][j];
    if(ans.ft>=0)return ans;
    ans=mk(0,1);
    if(i<n){
        pii tp=dfs(i+1,j);
        ans.ft+=tp.ft;ans.ft%=P;
        ans.se&=tp.se;
    }
    if(j<i){
        pii tp=dfs(i,j+1);
        ans.ft+=tp.ft;ans.ft%=P;
        ans.se&=tp.se;
    }
    if(ans.se==0){ans.ft++;ans.ft%=P;}
    ans.se^=1;
    return ans;
}
    
int main(){
    cin>>n;
    for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)dp[i][j]=mk(-1,-1);
    cout<<dfs(1,0).ft;
}

猜你喜欢

转载自www.cnblogs.com/VIrtu0s0/p/10812834.html