• CF1152 D. Neko and Aki's Prank


    题目传送门:https://codeforces.com/problemset/problem/1152/D

    题目大意:
    求一个长度为(2n)的所有合法括号序列构成的Trie树的最大匹配数(最大的边集使任意两条边无公共边)


    暴力画出一些(n)较小的Trie树后,我们可以发现一些规律:如果两点到根路径上左右括号数相同,则两点的子树形态一致

    基于这一点,我们直接Dfs+记忆化搜索即可

    /*program from Wolfycz*/
    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define Fi first
    #define Se second
    #define ll_inf 1e18
    #define MK make_pair
    #define sqr(x) ((x)*(x))
    #define pii pair<int,int>
    #define int_inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>inline T frd(T x){
    	int f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    template<typename T>inline T read(T x){
    	int f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e3,P=1e9+7;
    int F[N+10][N+10][2],n;
    bool vis[N+10][N+10];
    void Dfs(int L,int R){
    	if (vis[L-R][n-L])	return;
    	vis[L-R][n-L]=1;
    	if (L==R&&L==n)	return;
    	if (L<n&&L>R){
    		Dfs(L+1,R),Dfs(L,R+1);
    		int L0=F[L+1-R][n-L-1][0],L1=F[L+1-R][n-L-1][1];
    		int R0=F[L-R-1][n-L  ][0],R1=F[L-R-1][n-L  ][1];
    		F[L-R][n-L][1]=(L0+R0)%P;
    		F[L-R][n-L][0]=max(L0+R0,max(L1+R0+1,L0+R1+1))%P;
    		return;
    	}
    	if (L<n){
    		Dfs(L+1,R);
    		F[L-R][n-L][1]=F[L+1-R][n-L-1][0]%P;
    		F[L-R][n-L][0]=max(F[L+1-R][n-L-1][0],F[L+1-R][n-L-1][1]+1)%P;
    	}
    	if (L>R){
    		Dfs(L,R+1);
    		F[L-R][n-L][1]=F[L-R-1][n-L][0]%P;
    		F[L-R][n-L][0]=max(F[L-R-1][n-L][0],F[L-R-1][n-L][1]+1)%P;
    	}
    }
    int main(){
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n=read(0),Dfs(0,0);
    	printf("%d
    ",F[0][n][0]);
    	return 0;
    }
    
    作者:Wolfycz
    本文版权归作者和博客园共有,欢迎转载,但必须在文章开头注明原文出处,否则保留追究法律责任的权利
  • 相关阅读:
    C++中操作符函数
    C++中的类
    大型网站系统架构的演化
    GitHub初体验(小菜新手github用起来)
    黄聪:Adobe CS4 中文版 完美破解版下载
    WIN7下回收站不小心删除的文件怎么恢复,免费数据恢复软件下载
    PowerDesigner使用教程
    黄聪:CodeSmith和PowerDesigner的使用安装和数据库创建(原创系列教程)
    ORACLE SEQUENCE用法
    C++ DirectUI库收集
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/14985363.html
Copyright © 2020-2023  润新知