• Bzoj4350 括号序列再战猪猪侠


    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 97  Solved: 44

    Description

    括号序列与猪猪侠又大战了起来。
    众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号
    序列S合法,当且仅当:
    1.( )是一个合法的括号序列。
    2.若A是合法的括号序列,则(A)是合法的括号序列。
    3.若A,B是合法的括号序列,则AB是合法的括号序列。
    我们考虑match[i]表示从左往右数第i个左括号所对应的是第几个右
    括号,现在他得到了一个长度为2n的括号序列,给了你m个信息,第i
    个信息形如ai,bi,表示match[ai]<match[bi],要你还原这个序列。
    但是你发现这个猪猪侠告诉你的信息,可能有多个括号序列合法;甚
    至有可能告诉你一个不存在合法括号序列的信息!
    你最近学了取模运算,你想知道答案对998244353(7*17*2^23+1)取
    模的结果,这个模数是一个质数。

    Input

    第一行一个正整数T,T< = 5,表示数据组数。
    对于每组数据,第一行一个n,m,n表示有几个左括号,m表示信息数。
    接下来m行,每行两个数ai,bi,1< = ai,bi< = n。
     

    Output

    对于每组数据,输出一个数表示答案。
     

    Sample Input

    5
    1 0
    5 0
    3 2
    1 2
    2 3
    3 2
    2 1
    2 3
    3 3
    1 2
    2 3
    3 1

    Sample Output

    1
    42
    1
    2
    0

    HINT

     对于前两个点,是卡特兰数的情况。


    对于第三个点,合法的情况只可能是 ()()()。

    对于第四个点,合法情况可能是 (()()) 或者 (())()

    对于第五个点,由于拓扑关系形成了环,显然无解。

     

    对于 100% 的数据,保证 n < = 300

    动态规划 区间DP 脑洞题

    这两个家伙怎么打起来没完没了……

    既然求方案数,那就愉快地DP吧。

    考虑可能会有哪些情况:

    只依据左括号进行决策,不表示出右括号,设f[i][j]为第i个到第j个左括号(和它们的右括号)构成的括号序列的方案数。

    设last为一个已有的完整括号序列,新加入一对括号,可能有三种情况:

    1、(last)  这要求从 i+1 到 j 范围内没有“右括号在 i 后面”的限制条件

    2、()last   这要求从i+1 到 j 范围内没有 “右括号在 i 前面”的限制条件

    3、( la ) st  枚举区间断点k,分别满足上面的条件

    讨论三种情况进行转移即可。

    注意特判有自环的情况。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #define LL long long
     7 using namespace std;
     8 const int mod=998244353;
     9 const int mxn=305;
    10 int read(){
    11     int x=0,f=1;char ch=getchar();
    12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    14     return x*f;
    15 }
    16 int S[mxn][mxn],mp[mxn][mxn];
    17 int f[mxn][mxn];
    18 int n,m;
    19 void init(){
    20     memset(S,0,sizeof S);
    21     memset(mp,0,sizeof mp);
    22     memset(f,0,sizeof f);
    23     return;
    24 }
    25 int s(int x1,int y1,int x2,int y2){
    26     return S[x2][y2]-S[x1-1][y2]-S[x2][y1-1]+S[x1-1][y1-1];
    27 }
    28 int main(){
    29     int i,j,u,v;
    30     int T=read();
    31     while(T--){
    32         init();
    33         n=read();m=read();
    34         bool flag=0;
    35         for(i=1;i<=m;i++){
    36             u=read();v=read();
    37             mp[u][v]=1;
    38             if(u==v)flag=1;
    39         }
    40         if(flag){puts("0");continue;}
    41         for(i=1;i<=n;i++)
    42             for(j=1;j<=n;j++)
    43                 S[i][j]=S[i][j-1]+mp[i][j];
    44         for(i=1;i<=n;i++)
    45             for(j=1;j<=n;j++)
    46                 S[i][j]+=S[i-1][j];
    47         //
    48         for(i=1;i<=n;i++)f[i][i]=1;
    49         for(int st=2;st<=n;st++){
    50             for(i=1;i+st-1<=n;i++){
    51                 j=i+st-1;
    52                 if(!s(i,i+1,i,j))f[i][j]=(f[i][j]+f[i+1][j])%mod;// ( last )
    53                 if(!s(i+1,i,j,i))f[i][j]=(f[i][j]+f[i+1][j])%mod;// ()last
    54                 for(int k=i+1;k<j;k++){ //(la)st
    55                     if(!s(i,i+1,i,k) && !s(k+1,i,j,k)){
    56                         f[i][j]=((LL)f[i][j]+(LL)f[i+1][k]*f[k+1][j]%mod)%mod;
    57                     }
    58                 }
    59             }
    60         }
    61         printf("%d
    ",f[1][n]);
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    Windows Vista 桌面窗口管理器(1)
    Thinking in Java读书笔记――数组
    php图片上传存储源码,可实现预览
    php at(@)符号的用法简介
    Apache如何添加虚拟目录
    也发个PHP人民币金额数字转中文大写
    PHP Get Current URL
    Zend Studio下的PHP代码调试
    PHP url 加密解密函数
    使用新浪微博php SDK的一点记录
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/7061356.html
Copyright © 2020-2023  润新知