1526. Martian Plates

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;
}
相關文章
相關標籤/搜索