ch_POJ2411 Mondriaan's Dream

比较巧妙的状压!

需要扩展的一半的为1,其余为0,

上下两行|一下就是横着放的格子

注意预处理与M有关!

本行:i&1

上行:i&1^1

从一行开始,则初始化0行

#include<iostream>
#include<cstdio>

#define ri register int
#define u long long

namespace opt {

    inline u in() {
        u x(0),f(1);
        char s(getchar());
        while(s<'0'||s>'9') {
            if(s=='-') f=-1;
            s=getchar();
        }
        while(s>='0'&&s<='9') {
            x=(x<<1)+(x<<3)+s-'0';
            s=getchar();
        }
        return x*f;
    }

}

using opt::in;

#define NN 5005
#define MO 1000000000

#include<algorithm>
#include<cmath>
#include<cstring>

namespace mainstay {

    u N,M,can[NN],f[2][NN];

    inline void solve() {

        while(1) {
            N=in(),M=in();
            if(!N&&!M) return;
            std::memset(can,0,sizeof(can));
            for(ri i(0); i<(1<<M); ++i) {
                u _now(0);
                for(ri j(0); j<=M-1; ++j) {
                    if((i>>j)&1) can[i]|=_now,_now=0;
                    else _now^=1;
                }
                can[i]|=_now;
            }
            std::memset(f,0,sizeof(f));
            f[0][0]=1;
            for(ri i(1); i<=N; ++i) {
                std::memset(f[i&1],0,sizeof(f[i&1]));
                for(ri j(0); j<(1<<M); ++j) {
                    for(ri k(0); k<(1<<M); ++k) {
                        if(!(j&k)&&!can[k|j]) f[i&1][j]+=f[i&1^1][k];
                    }
                }
            }
            std::cout<<f[N&1][0]<<std::endl;
        }
    }

}

int main() {

    //freopen("x.txt","r",stdin);
    std::ios::sync_with_stdio(false);
    mainstay::solve();

}
原文地址:https://www.cnblogs.com/ling-zhi/p/11823084.html