POJ 2411 Mondriaan's Dream(状压DP)
来源:互联网 发布:手机怎么连接电脑网络 编辑:程序博客网 时间:2024/06/05 16:59
Mondriaan’s Dream
Description
Expert as he was in this material, he saw at a glance that he’ll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won’t turn into a nightmare!
Input
Output
Sample Input
1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0
Sample Output
1
0
1
2
3
5
144
51205
Source
[Submit]
[Go Back] [Status]
[Discuss]
题意
给你一个大小为
h∗w 的方格,让你用1∗2 的多米诺骨牌将该棋盘覆盖满,求方案数。
思路
这题由于h,w的范围非常小,所以我们可以很轻易地想到状压DP。
P.S. 本题题解参考http://blog.csdn.net/xingyeyongheng/article/details/21692655
对于第k行第j列,有3种情况将该点铺满由第k-1行第j列砖竖着铺将第k行第j列铺满
由第k行第j列被横铺砖铺满
第k行第j列砖竖着铺将该点铺满所以对于每一列的情况其实有两种(1,0)表示该点铺砖还是不铺
而对于每一列必须到达的状态只有一种,就是被铺满(1)
但是由上述3种情况将铺满方式分成两种:
0和1表示被k-1行j列竖铺铺满和在k-1行被横铺铺满
对于每一行列举每一种到达的状态j,dp[j]表示到达该状态有多少种情况
分析对于第k-1行状态j:10000111
需要到达第k行状态i: 01111011
如果需要到达第k行j列状态是0,则必须第k-1行该点状态不能是0,否则一定是连续两列竖放冲突
所以到达第k-1行该点只能是1,也就是说i|j一定每一位是1,也可以一步步判断是否满足第k行j列是0第k-1行j列是1
如果需要到达第k行状态j列是1,则假如第k-1行该点是0,则该点状态可以到达,继续判断j+1列
假如第k-1行该点是1,则第k行j列的1一定是横铺到达的,所以k行第j+1列一定也被铺满为1
从而第k-1行j+1列一定不能竖铺,必须被横铺铺满,所以也是1.
于是综合的第k行j列和第k-1行j列的关系(每一行每一列都表示到达的状态)1:下面这种情况从第j列继续去判断j+1列
1
0
2:下面这种情况从第j列继续去判断j+1列
0
1
3:下面这种情况从第j列判断第j+1列是否全是1,然后继续判断第j+2列
1
1
Code
#pragma GCC optimize(3)#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<cctype>#include<climits>#include<cstdlib>#include<cmath>#include<queue>#include<stack>#include<climits>#include<vector>using namespace std;typedef long long ll;inline void readInt(int &x) { x=0;int f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); x*=f;}inline void readLong(ll &x) { x=0;int f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); x*=f;}/*================Header Template==============*/const int maxn=(1<<11);ll f[2][maxn];int maxstatus[12],n,m;bool mark[maxn];inline void init(){maxstatus[0]=1;for(int i=1;i<=11;i++)maxstatus[i]=maxstatus[i-1]*2;}inline bool check(int statu) { while(statu) { if(statu&1) { statu>>=1; if(!(statu&1)) return 0; statu>>=1; } else statu>>=1; } return 1;}int main() { init(); while(scanf("%d%d",&n,&m)==2&&n&&m) { memset(f,0,sizeof f); memset(mark,0,sizeof mark); if((!n)||(!m)||((n*m)&1)) { puts("0"); continue; } if(n<m) swap(n,m); for(int sta=0;sta<maxstatus[m];sta++) if(check(sta)) { f[0][sta]=1; mark[sta]=1; } int now=0; for(int i=2;i<=n;i++) { now^=1; for(int sta=0;sta<maxstatus[m];sta++) f[now][sta]=0; for(int sta=0;sta<maxstatus[m];sta++) { for(int pre=0;pre<maxstatus[m];pre++) { if((sta|pre)!=maxstatus[m]-1||(!mark[sta&pre])) continue; f[now][sta]+=f[now^1][pre]; } } } printf("%lld\n",f[now][maxstatus[m]-1]); } return 0;}
- POJ 2411 Mondriaan's Dream (状压DP)
- Mondriaan's Dream - POJ 2411 状压dp
- POJ 2411 Mondriaan's Dream (状压DP)
- poj 2411 Mondriaan's Dream 状压dp
- poj 2411 Mondriaan's Dream(状压dp)
- POJ 2411 Mondriaan's Dream 状压dp
- POJ 2411 Mondriaan's Dream ( 状压DP )
- Mondriaan's Dream POJ - 2411 状压DP
- POJ 2411 Mondriaan's Dream (状压dp)
- POJ 2411 Mondriaan's Dream 状压dp
- [POJ 2411]Mondriaan's Dream:状压DP
- POJ 2411 Mondriaan's Dream (状压DP)
- poj 2411 Mondriaan's Dream 【状压dp】
- POJ 2411 Mondriaan's Dream(状压DP)
- poj 2411 Mondriaan's Dream(状压DP)
- POJ 2411 Mondriaan's Dream(状压 dp)
- POJ 2411 Mondriaan's Dream (状压DP)
- 【POJ 2411】Mondriaan's Dream(状压dp)
- MarkDown用法介绍
- Android6.0没有权限读取外部存储的问题
- [C++]数组初始化
- Discuz! X3.2手动升级到最新版本的方法?
- centos下Docker在线安装
- POJ 2411 Mondriaan's Dream(状压DP)
- 牛顿法与拟牛顿法学习笔记(一)牛顿法
- chmod用数字来表示权限的方法
- JDK源码分析之ArrayList(二)
- Hibernate配置文件之映射文件配置(二)
- UE4里如何创建并播放摄像机动画
- 咦?浏览器都能做人脸检测了?
- 根据当前页码、总页数,设置页码并实现页码切换功能
- node实现分页查询