Mondriaan's Dream
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 9614   Accepted: 5548

Description

Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways. 

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

The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.

Output

For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.

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

挺有意思的一道DP,给你一片空地的长和宽,让你用1 * 2的长方形填充空地,使之填满,问有多少种不同的方案。
我是按照Discuss里的一位大神的思路写的,Orz。。。
用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

代码如下:PS:这里科普一下运算符的优先级 http://blog.csdn.net/acm_xmzhou/article/details/9804983

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set> using namespace std;
//#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a)) #define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 100 + 50;
const int maxw = 100 + 20;
const int MAXNNODE = 1000000 +10;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
#define eps 1e-8
#define mod 1000000007
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pi;
LL dp[30][1 << 12], i , j , m , n , key = 1;///d[i][j]中i为该状态行数,j为二进制表示的该行状态,1为有木块,0为没有
///d[i][j]的值为该状态下的方法数
void solve(int i , int s , int pos)
{
if(pos == m)///最后一列累加前i行的方法数
{
dp[i][s] += key;
return ;
}
solve(i , s , pos + 1);///不放木块等待下一行竖放
if(pos <= m - 2&&!(s&1 << pos)&&!(s&1 <<(pos + 1)))///可以横放:<= m - 2&&第pos位和第pos + 1位为0(无木块)
solve(i , s|1 << pos|1 << pos + 1 , pos + 2);///把pos和pos+ 1为改为1,然后继续从pos + 2位solve }
int main()
{
//ios::sync_with_stdio(false);
#ifdef Online_Judge
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // Online_Judge
while(scanf("%d%d",&n, &m),(m||n))
{
clr(dp , 0);
key = 1;
solve(1 , 0 , 0);///先求出第一行的状态
FORR(i , 2 , n)for(int j = 0 ; j < 1 << m ; j++)
{
if(dp[i - 1][j])key = dp[i - 1][j];
else continue;///i - 1行没放木块
solve(i , ~j&((1 << m) - 1) , 0);///只给j位取了反
}
printf("%lld\n",dp[n][(1 << m) - 1]);///终状态的方法数
}
return 0;
}

还有一位大神用的插头DP,看不懂就不解释了。。。
代码如下:
#include<iostream>
#include<cstring>
using namespace std;
long long f[2][1<<12],i,j,ps,p=0,c=1,n,m;
int main()
{
while (scanf("%d%d",&n,&m),n!=0)
{
memset(f[c],0,sizeof(f[c]));
f[c][(1<<m)-1]=1;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
{
swap(p,c);memset(f[c],0,sizeof(f[c]));
for (ps=0;ps<1<<m;ps++)
if (f[p][ps])
{
if (j>0&&(!(ps&(1<<j-1)))&&(ps&(1<<j))) f[c][ps|1<<(j-1)]+=f[p][ps];
if (!(ps&1<<j)) f[c][ps|1<<j]+=f[p][ps];
if (ps&1<<j) f[c][ps^1<<j]+=f[p][ps];
}
}
printf("%lld\n",f[c][(1<<m)-1]);
}
}

POJ 2411的更多相关文章

  1. 状压DP POJ 2411 Mondriaan'sDream

    题目传送门 /* 题意:一个h*w的矩阵(1<=h,w<=11),只能放1*2的模块,问完全覆盖的不同放发有多少种? 状态压缩DP第一道:dp[i][j] 代表第i行的j状态下的种数(状态 ...

  2. poj 2411 Mondriaan&#39;s Dream 【dp】

    题目:id=2411" target="_blank">poj 2411 Mondriaan's Dream 题意:给出一个n*m的矩阵,让你用1*2的矩阵铺满,然 ...

  3. Poj 2411 Mondriaan's Dream(压缩矩阵DP)

    一.Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, ...

  4. Mondriaan's Dream POJ - 2411

    Mondriaan's Dream POJ - 2411 可以用状压dp,但是要打一下表.暴力枚举行.这一行的状态.上一行的状态,判断如果上一行的状态能转移到这一行的状态就转移. 状态定义:ans[i ...

  5. poj 2411 Mondriaan's Dream(状态压缩dP)

    题目:http://poj.org/problem?id=2411 Input The input contains several test cases. Each test case is mad ...

  6. poj 2411 Mondriaan's Dream 轮廓线dp

    题目链接: http://poj.org/problem?id=2411 题目意思: 给一个n*m的矩形区域,将1*2和2*1的小矩形填满方格,问一共有多少种填法. 解题思路: 用轮廓线可以过. 对每 ...

  7. POJ 2411 Mondriaan&#39;s Dream (dp + 减少国家)

    链接:http://poj.org/problem?id=2411 题意:题目描写叙述:用1*2 的矩形通过组合拼成大矩形.求拼成指定的大矩形有几种拼法. 參考博客:http://blog.csdn. ...

  8. POJ 2411 Mondriaan's Dream/[二进制状压DP]

    题目链接[http://poj.org/problem?id=2411] 题意:给出一个h*w的矩形1<=h,w<=11.用1*2和2*1的小矩形去填满这个h*w的矩形,问有多少种方法? ...

  9. POJ 2411 Mondriaan's Dream:网格密铺类 状压dp

    题目链接:http://poj.org/problem?id=2411 题意: 给你一个n*m的网格 (1<=n,m<=11) ,往里面铺1*2或2*1的砖块,问你铺完这个网格有多少种不同 ...

  10. POJ 2411 解题报告

    传送门:http://poj.org/problem?id=2411 题目简述 有一个\(W\)行\(H\)列的广场,需要用\(1*2\)小砖铺满,小砖之间互相不能重叠,问 有多少种不同的铺法? 输入 ...

随机推荐

  1. Socket 心跳包机制总结

    跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着.事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一 ...

  2. JavaScript快速入门(六)——DOM

    概念扫盲 DOM DOM是 Document Object Model(文档对象模型)的缩写,是W3C(万维网联盟)的标准.DOM 定义了访问 HTML 和 XML 文档的标准:“W3C 文档对象模型 ...

  3. 分分钟教会你使用HTML写Web页面

    在学习怎样使用HTML编写网页之前,我们必须先搞清楚什么是HTML?当然了不是系统的给大家介绍HTML的前世今生,假设对其身世感兴趣的小伙伴能够去问度娘,她会给你想要的答案. 所谓HTML,就是我们常 ...

  4. linux shell编程指南第十八章------控制流结构

    在书写正确脚本前,大概讲一下退出状态.任何命令进行时都将返回一个退出状态.如 果要观察其退出状态,使用最后状态命令: $ echo $? 主要有4种退出状态.前面已经讲到了两种,即最后命令退出状态$ ...

  5. VC图形绘制双缓存的代码复用性讨论

    在前文中已经讨论了如何实现界面绘制双缓存的问题,前文网址如下: http://www.2cto.com/kf/201111/112429.html 双缓存的主要思路是:先把图形绘制到内存DC中,然后再 ...

  6. BCB/Delphi中常用的VCL函数说明(字符串函数)

    本文档是ccrun(老妖)根据网上资料整理而成. --------------------内存分配--------------------函数名称:AllocMem函数说明:在队中分配指定字节的内存块 ...

  7. 七个你无法忽视的Git使用技巧(转)

    与其他技术相比,Git应该拯救了更多开发人员的饭碗.只要你经常使用Git保存自己的工作,你就一直有机会可以将代码退回到之前的状态,因此就可以挽回那些你深夜里迷迷糊糊犯下的错误. 尽管这么说,Git的命 ...

  8. android中,如果使用imageButton可以在drawable 中设置一个selector,但是imageView设置不起作用

    android中,如果使用imageButton可以在drawable 中设置一个selector,但是imageView设置不起作用,只要把Imageview的src给去掉就成了,src捕获了bac ...

  9. java entry

    我希望要一个ArrayList<Entry>,类似C++中的pair, 可是Map.Entry是个接口,不能实例化,能够像以下这样写 HashMap<Integer, Integer ...

  10. &lt;ctype.h&gt; C语言标准库

    ctype.h是C标准函数库中的头文件,定义了一批C语言字符分类函数(C character classification functions),用于測试字符是否属于特定的字符类别.如字母字符.控制字 ...