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. EXT2/EXT3文件系统(一)

    整理自<鸟哥的Linux私房菜>,整理者:华科小涛http://www.cnblogs.com/hust-ghtao/ 1.文件系统概念引入 文件系统是一种存储和组织计算机数据的方法,它使 ...

  2. 如果一个Object对象可能是集合或者数组那么如何对其进行迭代

    需求:一个方法传入的参数是Object类型(假设对象为“items”,使用Object类型也是为了使用多态而增加方法复用性),但已知这个Object对象可能是集合,包括Collection和Map,也 ...

  3. fzu 1911 C. Construct a Matrix

    C. Construct a Matrix Time Limit: 1000ms Case Time Limit: 1000ms Memory Limit: 32768KB Special Judge ...

  4. iot表输出按主键列排序,heap表不是

    <pre name="code" class="html"> create table t1 (id char(10) primary key,a1 ...

  5. uva 140

    思路:暴力+剪枝 uva140 wa了好多次……数组开小了……!!! #include <iostream> #include <cstdio> #include <cm ...

  6. Python标准库:内置函数dict(iterable, **kwarg)

    本函数是从可迭代对象来创建新字典.比方一个元组组成的列表,或者一个字典对象. 样例: #dict() #以键对方式构造字典 d1 = dict(one = 1, two = 2, a = 3) pri ...

  7. POJ 1273 Drainage Ditches(网络流,最大流)

    Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover ...

  8. objective-c 中数据类型之中的一个 几何数据类型(CGPoint,CGSize,CGRect)

    // CGPoint 结构体数据原型, 用于声明一个点: /* Points. */ struct CGPoint { CGFloat x; CGFloat y; }; typedef struct ...

  9. 如何在eclipse dump Java内存占用情况和打印GC LOG

     当使用java开发应用程序发生内存泄露的时候,经常会需要dump内存,然后使用内存分析工具,比如Eclipse Memory Analyzer(一般称作MAT)工具. 本文将介绍如何在eclipse ...

  10. UNICODE和ANSI字符串的转换(解释了MultiByteToWideChar,WideCharToMultiByte,GetTextCharsetInfo,GetTextCharset,IsDBCSLeadByte,IsDBCSLeadByteEx,IsTextUnicode一共7个函数)

    继上集故事<多字符集(ANSI)和UNICODE及字符串处理方式准则 >,我们现在有一些特殊需求: 有时候我们的字符串是多字符型,我们却需要使用宽字符型:有的时候却恰恰相反. Window ...