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\n",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;
}

原文地址:https://www.cnblogs.com/Narh/p/11005191.html

时间: 2024-10-13 08:46:59

hdu 5181 numbers——思路+区间DP的相关文章

HDU 4632 Palindrome subsequence(区间dp,回文串,字符处理)

题目 参考自博客:http://blog.csdn.net/u011498819/article/details/38356675 题意:查找这样的子回文字符串(未必连续,但是有从左向右的顺序)个数. 简单的区间dp,哎,以为很神奇的东西,其实也是dp,只是参数改为区间,没做过此类型的题,想不到用dp,以后就 知道了,若已经知道[0,i],推[0,i+1], 显然还要从i+1 处往回找,dp方程也简单: dp[j][i]=(dp[j+1][i]+dp[j][i-1]+10007-dp[j+1][

hdu 4412 Sky Soldiers(区间DP)

Sky Soldiers Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 559    Accepted Submission(s): 181 Problem Description An airplane carried k soldiers with parachute is plan to let these soldiers j

hdu 4570 Multi-bit Trie 区间DP入门

Multi-bit Trie 题意:将长度为n(n <= 64)的序列分成若干段,每段的数字个数不超过20,且每段的内存定义为段首的值乘以2^(段的长度):问这段序列总的内存最小为多少? 思路:区间的最值,区间DP; 枚举长度,在初始化时,将长度和20比较,小于20看成是一段,大于20时,因为不能压缩,直接全部分割就是了:之后枚举区间内部的所有值,这是并不需要考虑将这个区间一分为二后各自的长度是否大于20,因为在子结构中已经计算好了:直接去最优解即可: #include<iostream>

HDU 5396 Expression (区间DP)

链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5396 设d[i][j] 代表i~j的答案.区间DP枚举(i, j)区间的断点,如果断点处的操作符是'*',那么该区间的答案可以直接加上d[i][k] *  d[k+1][j],因为乘法分配律可以保证所有的答案都会乘起来.如果是加法,需要加的 就是 左边的答案 乘 右边操作数的阶乘 加上 右边的答案乘左边操作数的阶乘,最后要确定左边操作和右边操作的顺序 因为每个答案里是统计了该区间所有的阶乘情况,因此

hdu 6049---Sdjpx Is Happy(区间DP+枚举)

题目链接 Problem Description Sdjpx is a powful man,he controls a big country.There are n soldiers numbered 1~n(1<=n<=3000).But there is a big problem for him.He wants soldiers sorted in increasing order.He find a way to sort,but there three rules to obe

hdu 5693 &amp;&amp; LightOj 1422 区间DP

hdu 5693 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5693 等差数列当划分细了后只用比较2个或者3个数就可以了,因为大于3的数都可以由2和3组合成. 区间DP,用dp[i][j]表示在i到j之间可以删除的最大数,枚举区间长度,再考虑区间两端是否满足等差数列(这是考虑两个数的),再i到j之间枚举k,分别判断左端点右端点和k是否构成等差数列(还是考虑两个数的),判断左端点,k,右端点是否构成等差数列(这是老驴三个数的) 1 #include

hdu 4597 Play Game 区间dp

Play Game Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4597 Description Alice and Bob are playing a game. There are two piles of cards. There are N cards in each pile, and each card has a score. They take tur

!HDU 4283 屌丝联谊会-区间dp

题意:一群屌丝排队参加联谊,每个人都有屌丝值,如果他是第k个进场的,那么他的愤怒值就是(K-1)*Di,主办方想使所有屌丝的愤怒值总和最小,就用一个黑屋子来改变屌丝的进场顺序,黑屋子实际上是一个栈,先进后出.现在要求用这个栈能得到的最小的愤怒值总和是多少. 分析: 难点在于你不知道用了多少次黑屋子.用在哪些人身上以及每次各自进黑屋子的人数.很容易知道每个决策都会影响最终结果,那么我们就想用dp来做.问题是哪种dp,本题实际上就是在区间上求最优解,所以用区间dp.区间dp就是每次把一个区间分成两个

【DP】 HDU 5115 Dire Wolf 区间DP

点击打开链接 题意:一头狼的攻击力= 自己攻击力+相邻两边的狼的加成 每杀一头狼会收到一次攻击 求受到的攻击和最小 比较裸的区间DP #include <cstdio> #include <cstring> #include <cstdlib> #include <string> #include <iostream> #include <algorithm> #include <sstream> #include <