SGU131 状态压缩~覆盖方案数

来源:互联网 发布:表达爱意的网络用语 编辑:程序博客网 时间:2024/06/10 13:25

做这个题前前后后磨了3天,感觉自己弱爆了;总算理解好了,不过收获也很大,发现之前状态理解错了,做这个题的时候,发现论文里面的状态转移完全无法理解,然后去找各种解题报告,让我恍然大悟的一句话是:“因为已经做到了第i行,那么i-1行一定要求是满的。”,这是在Wrongswer空间看到的一句话,对于dfs中pre,now状态转换顿时就明白了。而且这个解题报告状态的解释也很清楚,值得一看。为了加深自己的理解,就写了个反状态的压缩,dfs的时候思考清楚就好了,预处理做好了接下来的就跟之前的题目一样一样了大笑。还有一点,题目空间给的小,存储状态的数组不要开太大,否则会MEL。


ACcode:

#include<cstdio>#include<cstring>typedef long long LL;const int NS=79248;const int LIM=1<<9;LL dp[2][LIM];int state[NS][2],top;void dfs(int pre,int now,int pf,int nf,int pos){    if (pos==0)    {        if (pf&&nf)            state[top][0]=pre,            state[top++][1]=now;        return ;    }    dfs((pre<<1|1)-pf,(now<<1)+nf,1,1,pos-1); //不放    if (pf&&nf)        dfs(pre<<1|1,now<<1,1,1,pos-1),       //竖直放        dfs(pre<<1|1,now<<1,0,1,pos-1),       //缺右下        dfs(pre<<1|1,now<<1,1,0,pos-1);       //缺右上    if (nf)        dfs((pre<<1|1)-pf,now<<1,0,0,pos-1);  //缺左上    if (pf)        dfs(pre<<1|1,(now<<1)+nf,0,1,pos-1),  //横放        dfs(pre<<1|1,(now<<1)+nf,0,0,pos-1);  //缺左下}void init(int x){    for (int i=0; i<LIM; i++)        dp[x][i]=0;}void print(int x,int y){    for (int i=0; i<y; i++)        printf("%d",(x>>i)&1);}int main(){    int n,m,p,q,s;    while (~scanf("%d %d",&n,&m))    {        init(0),top=s=0;        if (n<m) n^=m,m^=n,n^=m;        dp[0][(1<<m)-1]=1,dfs(0,0,1,1,m);        for (int i=0; i<n; i++)        {            s^=1,init(s);            for (int j=0; j<top; j++)                p=state[j][0],q=state[j][1],                dp[s][q]+=dp[s^1][p];        }        printf("%I64d\n",dp[s][(1<<m)-1]);    }    return 0;}