【题目分析】

用1*2的牌铺满n*m的格子。

刚开始用到动规想写一个n*m*2^m,写了半天才知道会有重复的情况。

So Sad。

然后想到数据范围这么小,爆搜好了。于是把每一种状态对应的转移都搜了出来。

加了点优(gou)化(pi),然后poj上1244ms垫底。

大概的方法就是考虑每一层横着放的情况,剩下的必须竖起来的情况到下一层取反即可。

然后看了 《插头DP-从入门到跳楼》 这篇博客,怒抄插头DP

然后16ms了,自己慢慢YY了一下,写出了风(gou)流(pi)倜(bu)傥(tong)的代码

UPD:发现完全不需要轮廓线,直接把轮廓线断开一小段就可以转移了,更加坚定自己的算法渣了

【代码】

状压DP

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
ll dp[12][1<<12];
int pos[12],n,m,to[1<<12];
void print(int x){F(i,0,m-1)printf("%d",(x>>i)&1);}
void dfs(int x)
{
if (to[x]) return ;
to[x]=1;
F(i,0,m-2)
if ((!(x&pos[i]))&&(!(x&pos[i+1])))
dfs(x|pos[i]+pos[i+1]);
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF&&n&&m)
{
memset(dp,0,sizeof dp); int all=(1<<m)-1;
F(i,0,m) pos[i]=1<<i; dp[0][(1<<m)-1]=1;
F(i,0,n-1)
{
F(j,0,(1<<m)-1)
{
memset(to,0,sizeof to);
int aim=j^all; dfs(aim);
F(k,0,(1<<m)-1)
if (to[k]) dp[i+1][k]+=dp[i][j];
}
}
printf("%lld\n",dp[n][(1<<m)-1]);
}
}

  插头DP

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; long long dp[2][1<<11]; int main()
{
int n,m;
while(scanf("%d%d",&n,&m),(n||m))
{
int total=1<<m;
int pre=0,now=1;
memset(dp[now],0,sizeof(dp[now]));
dp[now][0]=1; for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
swap(now,pre);
memset(dp[now],0,sizeof(dp[now])); for(int S=0;S<total;S++) if( dp[pre][S] )
{
dp[now][S^(1<<j)]+=dp[pre][S];
if( j && S&(1<<(j-1)) && !(S&(1<<j)) )
dp[now][S^(1<<(j-1))]+=dp[pre][S];
}
} printf("%lld\n",dp[now][0]);
}
}

  自己写的代(gou)码(pi)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define F(i,j,k) for (int i=j;i<=k;++i)
ll dp[2][1<<12];
int n,m;
void print(int x)
{F(i,0,m)printf("%d",(x>>i)&1);}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF&&n&&m)
{
if (n<m) swap(n,m);
int now=1,pre=0;
memset(dp[now],0,sizeof dp[now]);
dp[now][0]=1;
F(i,0,n-1)
F(j,0,m-1)
{
now^=1;pre^=1;
memset(dp[now],0,sizeof dp[now]);
F(s,0,(1<<(m+1))-1) if (dp[pre][s])
{
if ((s&(1<<j))&&!(s&(1<<(j+1)))) dp[now][s^(1<<j)]+=dp[pre][s];
if (!(s&(1<<j))&&!(s&(1<<(j+1)))) dp[now][s^(1<<j)]+=dp[pre][s],dp[now][s^(1<<(j+1))]+=dp[pre][s];
if (!(s&(1<<j))&&(s&(1<<(j+1)))) dp[now][s^(1<<(j+1))]+=dp[pre][s];
}
if (j==m-1)
{
now^=1;pre^=1;
memset(dp[now],0,sizeof dp[now]);
F(s,0,(1<<m)-1) if (dp[pre][s]&&!(s&(1<<m)))
dp[now][(s<<1)&((1<<(m+1))-1)]+=dp[pre][s];
}
}
printf("%lld\n",dp[now][0]);
}
}

POJ 2411 Mondriaan's Dream ——状压DP 插头DP的更多相关文章

  1. POJ 2411 Mondriaan's Dream -- 状压DP

    题目:Mondriaan's Dream 链接:http://poj.org/problem?id=2411 题意:用 1*2 的瓷砖去填 n*m 的地板,问有多少种填法. 思路: 很久很久以前便做过 ...

  2. Poj 2411 Mondriaan's Dream(状压DP)

    Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Description Squares and rectangles fascina ...

  3. POJ 2411 Mondriaan'sDream(状压DP)

    题目大意:一个矩阵,只能放1*2的木块,问将这个矩阵完全覆盖的不同放法有多少种. 解析:如果是横着的就定义11,如果竖着的定义为竖着的01,这样按行dp只需要考虑两件事儿,当前行&上一行,是不 ...

  4. POJ 2411 Mondriaan's Dream 插头dp

    题目链接: http://poj.org/problem?id=2411 Mondriaan's Dream Time Limit: 3000MSMemory Limit: 65536K 问题描述 S ...

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

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

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

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

  7. POJ 2411 Mondriaan's Dream 【状压Dp】 By cellur925

    题目传送门 这道题暑假做的时候太模糊了,以前的那篇题解大家就别看了==.今天再复习状压感觉自己当时在写些什么鸭.... 题目大意:给你一个\(n\)*\(m\)的棋盘和许多\(1*2\)的骨牌,骨牌可 ...

  8. [poj 2411]Mondriaan's Dream (状压dp)

    Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 18903 Accepted: 10779 D ...

  9. POJ 2411 Mondriaan's Dream (状压DP,骨牌覆盖,经典)

    题意: 用一个2*1的骨牌来覆盖一个n*m的矩形,问有多少种方案?(1<=n,m<=11) 思路: 很经典的题目,如果n和m都是奇数,那么答案为0.同uva11270这道题. 只需要m个b ...

随机推荐

  1. 对于HDMI设备连接状态的监听

    对与最近主要做的是电视机盒子端的开发,其中涉及到设备的状态监听比较繁琐,所以对HDMI的连接状态的监听方法做个记录,方便后续查看. 主要通过两种方式: (1)比较常用的广播监听 注册一个动态广播来获取 ...

  2. {ubuntu}不能挂载windows

    sudo apt-get install ntfs-3g sudo ntfsfix /dev/sda?

  3. NBUT 1116 Flandre's Passageway (LIS变形)

    题意: 给一个有n*m格子的矩形,设每格边长100,要从(1,1)走到(n,m)需要耗(n+m)*100,但是其中有一些格子是可以直接穿过的,也就是走对角线,是100*根号2长,给出k个可以穿过的格子 ...

  4. 洛谷 P2068 统计和

    题目描述 给定一个长度为n(n<=100000),初始值都为0的序列,x(x<=10000)次的修改某些位置上的数字,每次加上一个数,然后提出y (y<=10000)个问题,求每段区 ...

  5. leetcode 127 单词接龙

    给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度.转换需遵循如下规则: 每次转换只能改变一个字母. 转换过程中的中 ...

  6. 剑指offer——把字符串转换成整数(c++)

    题目描述请你写一个函数StrToInt,实现把字符串转换成整数这个功能.当然,不能使用atoi或者其他类似的库函数. 示例 1:输入: " -42"输出: -42解释: 第一个非空 ...

  7. CAD交互绘制圆形云线批注(网页版)

    js中实现代码说明: 动态拖放时的绘制事件: function DoDynWorldDrawFun(dX,dY,pWorldDraw,pData) { //自定义实体的GUID标识符 var sGui ...

  8. BestCoder Round#15 1002-Instruction

    http://acm.hdu.edu.cn/showproblem.php?pid=5083 官方题解——> 1002 Instruction 先考虑编码,首先找到operation对应的编码, ...

  9. vue 动态合并单元格、并添加小计合计功能

    1.效果图 2.后台返回数据格式(平铺式) 3.后台返回数据后,整理所需要展示的属性存储到(items)数组内 var obj = { "id": curItems[i].id, ...

  10. activiti整合开发实例总结

    参考手册:http://www.mossle.com/docs/activiti/ 一.applicationContext.xml中引入activiti相关配置的xml文件 <!-- begi ...