zoukankan      html  css  js  c++  java
  • hdu 5181 numbers——思路+区间DP

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5181

    题解:https://www.cnblogs.com/Miracevin/p/10960717.html

    原来卡特兰数的这个问题还能区间DP……

    XO

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int N=305,M=9e5+5,mod=1e9+7;
    int n,m,hd[N],xnt,to[M],nxt[M],b[N][N],f[N][N];
    bool vis[N];
    void init()
    {
      memset(b,0,sizeof b); memset(f,0,sizeof f);
      xnt=0; memset(hd,0,sizeof hd);
    }
    void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
    void dfs(int cr)
    {
      for(int i=hd[cr],v;i;i=nxt[i])
        if(!vis[v=to[i]])
          {
        vis[v]=1; b[cr][v]=1; dfs(v);
          }
    }
    bool chk(int x1,int x2,int y1,int y2)
    {
      if(x2<x1||y2<y1)return true;
      int tp=b[x2][y2]-b[x1-1][y2]-b[x2][y1-1]+b[x1-1][y1-1];
      return !tp;
    }
    void solve()
    {
      for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
          b[i][j]+=b[i][j-1];
      for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
          b[i][j]+=b[i-1][j];
      for(int len=1;len<=n;len++)
        {
          for(int i=1;i<=n;i++)
        {
          int j=i+len-1; if(j>n)break;
          f[i][i-1]=f[j+1][j]=1;
          for(int k=i;k<=j;k++)
            {
              if(chk(k,j,i,k-1)&&chk(k,k,k+1,j))
            f[i][j]=(f[i][j]+(ll)f[i][k-1]*f[k+1][j])%mod;
            }
        }
        }
      printf("%d
    ",f[1][n]);
    }
    int main()
    {
      int T=rdn();
      while(T--)
        {
          init();
          n=rdn();m=rdn();
          for(int i=1,u,v;i<=m;i++)
        u=rdn(),v=rdn(),add(u,v);
          for(int i=1;i<=n;i++)
        {
          memset(vis,0,sizeof vis);
          dfs(i);
        }
          bool fg=0;
          for(int i=1;i<=n&&(!fg);i++)
        for(int j=1;j<=i;j++)
          if(b[i][j]&&b[j][i]){fg=1;break;}
          if(fg){puts("0");continue;}
          solve();
        }
      return 0;
    }
  • 相关阅读:
    计算机网络概述
    虚拟机网卡配置
    元类
    反射和内置方法
    面向对象的三大特性
    MYSQL中EXISTS的用法
    Guava中的常见集合操作用法
    集合操作交并补的三种Java实现
    P9 get和resize操作(Java 13)
    P8 Java 13中 HashMap的 put方法
  • 原文地址:https://www.cnblogs.com/Narh/p/11005191.html
Copyright © 2011-2022 走看看