SGU131 状态压缩~覆盖方案数

做这个题前前后后磨了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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值