1526. Martian Plates

http://acm.timus.ru/problem.aspx?space=1&num=1526

题目大意:

可以从n个碟子中任选一个放在桌子上(不断往上放),也可以把桌子上最顶端的盘子拿走

对于约束条件 i , j 是说假如 i 这个碟子还在桌子上,就不能拿走 j 这个碟子,也就等于放了

i 这个碟子就不能再放 j 了,因为放了 i 再放 j,就会相互约束,无法拿走碟子了。

思路:

可以把问题转化为括号匹配队列问题,左括号代表拿来碟子,右括号代表拿走碟子。

dp[x][y]  , x 代表还有x个碟子可以放,y 代表已经放了的碟子的状态压缩表示

再放的形式就是  “ ( 递归1 ) 递归2  ”,根据y可以判定哪些括号可以放,枚举可以放的括号

括号确定后还要 枚举 “递归1” 的括号数量(偶数),对应的y需要更新,在 “递归1” 括号数量确定的情况下

“递归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;

}

 

你可能感兴趣的:(r)