zoukankan      html  css  js  c++  java
  • [题解]Codeforces1152D. Neko and Aki's Prank

    不知道为什么又用回了mkd

    题目描述

    在括号树上找最大匹配

    分析

    首先最大匹配可以看成:

    每次选择一条连接两个没有染过色的点的边,把两个点染色。直到不能再选为止。问最多能选择几条边。

    可以发现,括号树的很多子树都是相同的——当左右括号数相同的时候

    (f[i][j])为当前左右括号一共用了(i)个,左括号比右括号多了(j)个的节点子树的最大匹配数之和。

    (f[i][j]=left{egin{matrix}f[i+1][j+1]+f[i+1][j-1]+1 & col[i+1][j]!=0||col[i+1][j-1]!=0\ f[i+1][j+1]+f[i+1][j-1]& else end{matrix} ight.)

    就是说,如果当前点的两个儿子(最多)中至少有一个没有被染色,那么这个节点就可以被选,否则就不行。

    这里其实用到了贪心,就是默认选叶子节点,这里有证明,太懒不想写XD

    转移的时候还要特判合法

    代码

    #include<bits/stdc++.h>
    #define rep(X,A,B) for(int X=A;X<=B;X++)
    #define tep(X,A,B) for(int X=A;X>=B;X--)
    #define LL long long
    const int N=2010;
    const LL MOD=1e9+7;
    using namespace std;
    
    int n,col[N][N];
    LL f[N][N];
    
    int main(){
    	scanf("%d",&n);
    	tep(i,2*n-1,0){
    		for(int j=0;i+j<=2*n;j++){
    			int flag=1;
    			if(j!=0){
    				f[i][j]+=f[i+1][j-1];
    				f[i][j]%=MOD;
    				if(col[i+1][j-1]!=0)flag=0;
    			}
    			if(i+j<=2*n){
    				f[i][j]+=f[i+1][j+1];
    				f[i][j]%=MOD;
    				if(col[i+1][j+1]!=0)flag=0;
    			}
    			if(flag)col[i][j]=1,f[i][j]=(f[i][j]+1)%MOD;
    		}
    	}
    	printf("%lld
    ",f[0][0]);
    	return 0;
    }
    
  • 相关阅读:
    高计数率下的梯形成形算法的计数率矫正
    梯形成形算法
    就业还是和一起创业?
    努力,还是会前进,世界一定是越来越好。
    一日黑客,SQL注入
    钱,money,人生
    一些技术生词记录
    江苏省计算机C语言考试记录
    NVIDIA显卡设置
    大二寒假 之 丢失的13天
  • 原文地址:https://www.cnblogs.com/SCL123/p/10804418.html
Copyright © 2011-2022 走看看