http://acm.timus.ru/problem.aspx?space=1&num=1526ios
题目大意:spa
能够从n个碟子中任选一个放在桌子上(不断往上放),也能够把桌子上最顶端的盘子拿走blog
对于约束条件 i , j 是说假如 i 这个碟子还在桌子上,就不能拿走 j 这个碟子,也就等于放了递归
i 这个碟子就不能再放 j 了,由于放了 i 再放 j,就会相互约束,没法拿走碟子了。队列
思路:get
能够把问题转化为括号匹配队列问题,左括号表明拿来碟子,右括号表明拿走碟子。string
dp[x][y] , x 表明还有x个碟子能够放,y 表明已经放了的碟子的状态压缩表示it
再放的形式就是 “ ( 递归1 ) 递归2 ”,根据y能够断定哪些括号能够放,枚举能够放的括号io
括号肯定后还要 枚举 “递归1” 的括号数量(偶数),对应的y须要更新,在 “递归1” 括号数量肯定的状况下class
“递归2” 的括号数量也肯定了,对于“递归2” y 不须要更新
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std; const int N=205; const int M=(1<<10); int dp[N][M]; int p,t,n,m; vector<int>unlike[N]; int put[M][11]; int fput(int y,int i) { if(put[y][i]!=-1) return put[y][i]; for(unsigned int j=0;j<unlike[i].size();++j) { int k=unlike[i][j]; if((y&(1<<k))>0) return (put[y][i]=0); } return (put[y][i]=1); } int dfs(int x,int y) { if(dp[x][y]!=-1) return dp[x][y]; if(x==0) return (dp[x][y]=1); dp[x][y]=0; for(int i=0;i<n;++i) if(fput(y,i)==1) { for(int j=0;j+2<=x;j+=2) { dp[x][y]+=(dfs(j,y|(1<<i))*dfs(x-2-j,y)); dp[x][y]%=p; } } return dp[x][y]; } int main() { //freopen("data.in","r",stdin); scanf("%d %d %d %d",&p,&t,&n,&m); while(m--) { int i,j; scanf("%d %d",&i,&j); --i;--j; unlike[j].push_back(i); } memset(dp,-1,sizeof(dp)); memset(put,-1,sizeof(put)); printf("%d\n",dfs(t,0)); return 0; }