zoukankan      html  css  js  c++  java
  • 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
    本文版权归作者和博客园共有,欢迎转载,但必须在文章开头注明原文出处,否则保留追究法律责任的权利
  • 相关阅读:
    mouse without borders无界鼠标使用教程
    动态令牌-(OTP,HOTP,TOTP)-基本原理
    sha256C代码例子
    常用的前端设计工具分享
    PHP获取搜索引擎关键字来源(百度、谷歌、雅虎、搜狗、搜搜、必应、有道)
    为 Web 设计师准备的 25+ 款扁平 UI 工具包
    万能字段使用技巧整理
    css中overflow:hidden的属性 可能会导致js下拉菜单无法显示
    QQ空间g_tk加密算法PHP版
    QQ聊天机器人for PHP版 (登录,收、发消息)
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/14985363.html
Copyright © 2011-2022 走看看