POJ 2411. Mondriaan‘s Dream

链接

http://poj.org/problem?id=2411

题意

求把 n ∗ m n*m nm 的棋盘分割成若干个 1 ∗ 2 1*2 12 的的长方形有多少种方案

思路

状压 DP

对于每一行设某单位格是竖着的 1 ∗ 2 1*2 12 的长方形的上半部分的状态为 1 1 1,其余状态为 0 0 0

对于下一行,如果上行状态为 1 1 1 的单元格该行都为 0 0 0,即上行状态与该行状态按位与值为 0 0 0,则可以转移

与上行按位或后,代表该行所有是竖着的长方形的下半部分的单位格匹配成功,那么剩下的 0 0 0 肯定是横着的长方形,所以每个 0 0 0 段必须是偶数段

预处理每个状态的 0 0 0 段是否都是偶数段

然后枚举 2 m 2^m 2m 个状态转移即可

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
bool st[1<<11];
ll f[12][1<<11];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    while(cin>>n>>m&&n) {
        for(int i=0;i<1<<m;i++) {
            int cnt=0;
            int fg=0;
            for(int j=0;j<m;j++) {
                if(i&(1<<j)) {
                    if(cnt&1) fg=1,cnt=0;
                    if(fg) break;
                }
                else cnt^=1;
            }
            st[i]=fg|cnt?false:true;
        }
        f[0][0]=1;
        for(int i=1;i<=n;i++)
            for(int j=0;j<1<<m;j++) {
                f[i][j]=0;
                for(int k=0;k<1<<m;k++)
                    if(!(k&j)&&st[k|j])
                        f[i][j]+=f[i-1][k];
            }
        cout<<f[n][0]<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值