POJ - 2411 Mondriaan's Dream 状压DP

本文介绍了一种使用2*1矩形铺满n*m矩形的算法,通过枚举状态和动态规划求解所有可能的铺法数量。算法采用二进制表示每行的铺放状态,通过位运算推导出下一行的可能状态,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

n*m的矩形用2*1的矩形铺满一共可以有多少种方法?

分析:

思路来自评论区大神的思路:

用2进制的01表示不放还是放
第i行只和i-1行有关
枚举i-1行的每个状态,推出由此状态能达到的i行状态
如果i-1行的出发状态某处未放,必然要在i行放一个竖的方块,所以我对上一行状态按位取反之后的状态就是放置了竖方块的状态。
然后用搜索扫一道在i行放横着的方块的所有可能,并且把这些状态累加上i-1的出发状态的方法数,如果该方法数为0,直接continue。
举个例子
2 4
1111
1111
状态可以由
1100 0000 0110 0011 1111
0000 0000 0000 0000 0000
这五种i-1的状态达到,故2 4 的答案为5

通俗易懂,学习了。

//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;

int n,m;

ll dp[12][1<<12];
ll tmp;

void solve(int i,int s,int pos){
    if(pos==m){
        dp[i][s]+=tmp;
        return ;
    }
    solve(i,s,pos+1);
    if(pos<=m-2&&!(s&(1<<pos))&&!(s&(1<<pos+1)))
        solve(i,s|(1<<pos)|(1<<pos+1),pos+2);
}

int main(){

    while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
        tmp=1;
        memset(dp,0,sizeof dp);
        solve(1,0,0);
        for(int i=2;i<=n;i++){
            for(int j=0;j<(1<<m);j++){
                if(dp[i-1][j]) tmp=dp[i-1][j];
                else continue;
                solve(i,(~j)&((1<<m)-1),0);
            }
        }
        printf("%lld\n",dp[n][(1<<m)-1]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值