UVa 11270 铺放骨牌(轮廓线DP)

https://vjudge.net/problem/UVA-11270

题意:

用1×2骨牌覆盖n×m棋牌,有多少种方法?

思路:

这道题目是典型的轮廓线DP题。

所谓轮廓线DP,就是以整行整列为状态进行动态规划时无法进行状态转移,那么此时就可以用到轮廓线,当然,这种方法只能使用在一个窄棋盘上,大了肯定是不行的,要超时!

轮廓线DP就是按照从上到下,从左到右的顺序进行状态转移,每个格子用二进制来表示状态,1代表的就是覆盖,0代表未覆盖。

以本题为例,如上图,我们现在要计算 k 格子,那么与它有关的就是k4 k3 k2 k1 k0这5个格子。

现在,我们对于每个格子都有三种决策:

1、不放

不放的条件是其上面的格子必须是1(也就是k4必须是1),否则无法覆盖所有的棋盘的。

如果满足条件,那么就进行状态转移,d[cur][新状态]+=d[1-cur][旧状态],也就是d[cur][k3k2k1k0k]+=d[1-cur][k4k3k2k1k0]

2、上放

上放的条件是其上面的格子必须是0。

3、左放

左放的条件其左边的格子必须是0。

具体的算法实现请参见代码。

注意:这道题目数组开小点,开到1<<15会TLE,11就可以了!!

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<sstream>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<cmath>
10 #include<map>
11 using namespace std;
12 typedef long long ll;
13 typedef pair<int,int> pll;
14 const int INF = 0x3f3f3f3f;
15 const int maxn=11;
16
17 int n,m;
18 int cur;
19 ll d[2][1<<maxn];
20
21 void update(int a,int b)   //a是m位的旧状态,b是m+1位的新状态
22 {
23     if(b&(1<<m))   d[cur][b^(1<<m)]+=d[1-cur][a];  //先检查新状态的轮廓线首是否为1,是1则更新状态
24 }                                                  //因为轮廓线首位1,所以b^(1<<m)就是将首位置为0,将新状态变成m位
25
26 int main()
27 {
28     while(scanf("%d%d",&n,&m)==2)
29     {
30         if(n<m)   swap(n,m);
31         memset(d,0,sizeof(d));
32         d[0][(1<<m)-1]=1;
33         cur=0;
34         for(int i=0;i<n;i++)
35         {
36             for(int j=0;j<m;j++)
37             {
38                 cur^=1;
39                 memset(d[cur],0,sizeof(d[cur]));
40                 for(int k=0;k < (1<<m);k++)
41                 {
42                     update(k,k<<1);  //不放,直接将二进制左移一位形成新状态
43                     if(i && !(k&(1<<m-1)))  update(k,(k<<1)^(1<<m)^1);  //上放,要求轮廓线首为0且为非首行
44                     if(j && !(k&1))  update(k,(k<<1)^3);  //左放,要求轮廓线首为1,尾为0,且为非首列
45                 }
46             }
47         }
48         printf("%lld\n",d[cur][(1<<m)-1]);
49     }
50     return 0;
51 }
时间: 2024-10-06 00:07:13

UVa 11270 铺放骨牌(轮廓线DP)的相关文章

UVA 11270 Tiling Dominoes(轮廓线DP经典)

题意:用1*2的骨牌覆盖n*m的棋盘有多少种方法 这道题注意一下不要按照大白书上把maxn开成15就好,因为每次都要memset如果开到15会tle,开到11就可以 #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #incl

poj 2411 Mondriaan&#39;s Dream 骨牌铺放 状压dp

题目链接 题意 用\(1\times 2\)的骨牌铺满\(H\times W(H,W\leq 11)\)的网格,问方案数. 思路 参考focus_best. 竖着的骨牌用\(\begin{pmatrix}0\\1\end{pmatrix}\)表示,横着的骨牌用\(\begin{pmatrix}1&1\end{pmatrix}\)表示. 则对于第\(i\)行,与之相容的第\(i-1\)行的状态需满足: 第\(i\)行是0的位置,第\(i-1\)行必须是1: 第\(i\)行是1的位置,第\(i-1\

UVA 10572 Black &amp; White (轮廓线DP)

题意:有一个n*m的矩阵,其中部分格子已经涂黑,部分涂白,要求为其他格子也上黑/白色,问有多少种涂法可以满足一下要求: (1)任意2*2的子矩阵不可以同色. (2)所有格子必须上色. (3)只能有两个连通分量(即1黑1白). 注:1<n,m<9.若能满足,顺便输出任一种涂色方法. 思路: 本来题也不难,只是刚开始写最小表示法,加上这题的难度,所以搞非常久.注:本题用最小表示法比较好. 大概逻辑如下: if g[i][j]非首列且2*2子矩阵同色 then 非法状态; if 上格连通分量不会丢失

uva 11270 - Tiling Dominoes(插头dp)

题目链接:uva 11270 - Tiling Dominoes 题目大意:用1?2木块将给出的n?m大小的矩阵填满的方法总数. 解题思路:插头dp的裸题,dp[i][s]表示第i块位置,并且该位置对应的行数的状态为s的时候的总情况数.0表示为竖放预留留的位置,1表示填上的位置,不管是竖放还是横放.并且第一位状态用滚动数组优化空间. #include <cstdio> #include <cstring> #include <algorithm> using names

poj 2411 Mondriaan&#39;s Dream (轮廓线DP)

题意:有一个n*m的棋盘,要求用1*2的骨牌来覆盖满它,有多少种方案?(n<12,m<12) 思路: 由于n和m都比较小,可以用轮廓线,就是维护最后边所需要的几个状态,然后进行DP.这里需要维护的状态数就是min(n,m).即大概是一行的大小.每次放的时候,只考虑(1)以当前格子为右方,进行横放:(2)以当前格子为下方进行竖放:(3)还有就是可以不放. 3种都是不一样的,所以前面的一种状态可能可以转为后面的几种状态,只要满足了条件.条件是,横放时,当前格子不能是最左边的:竖放时,当前格子不能是

【轮廓线DP】POJ2411-Mondriaan&#39;s Dream

今天美国的院士过来讲课XD以为会很无聊但是谜之好听,而且英语基本上都听懂了的样子?(´▽`) 逃到图书馆来写解题报告 [题目大意] 给出一个m*n的方格,用2*1的骨牌覆盖有几种情况. [思路] 最基础的轮廓线DP.分为三种情况: (1)向上放,必须要满足上面的格子没有被放,且当前不在首行.→新状态=旧状态删去首位,末尾为1: (2)向左放,必须要满足左边的格子和上面的格子都没有放,且当前不在首列.→新状态=旧状态删去首位,末两位微1: (3)不放,必须满足上面的格子没有放.新状态=旧状态删去首

hdu 4804 Campus Design 轮廓线dp

题意: 给出一个n*m的01矩阵,其中要求把矩阵里面的1用1*1或1*2的砖块铺满,矩阵里面的0为障碍物,问使用1*1的砖块数>=c && <=d 的方案有多少种. 限制: 1 <= n <= 100; 1 <= m <= 10; 1 <= c <= d <= 20; 思路: 因为 1 <= m <= 10 所以可以采用轮廓线dp, 具体状态解释在代码中说明. /*hdu 4804 Campus Design 轮廓线dp 题

uva 10529 - Dumb Bones(概率+区间dp)

题目连接:uva 10529 - Dumb Bones 题目大意:给定n,表示要放n个骨牌,每次放下骨牌,有可能向左倒的概率为pl,向右倒的概率为pr,如果倒下,会将那一侧的骨牌全部推倒,可以选择位置先后放骨牌,问说一种放骨牌次数最少的期望是多少. 解题思路:dp[i]表示放i个骨牌需要的步数期望,维护一个最优放的位置,dp[i] = min\{ (从i-1到i的步数)} + (0到i-1的步数)} (从i-1到i的步数):dp[i?j?1]?pl+dp[j]?pr+11?pl?pr (0到i-

2013 ACM-ICPC亚洲区域赛南京站C题 题解 轮廓线DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4804 题目大意 给你一个 \(n \times m\) 的矩形区域.你需要用 \(1 \times 1\) 和 \(1 \times 2\) 的砖块铺满这个区域,且满足如下要求: 所有的砖块可以竖着放或横着放: 砖角要放在格点上: \(1 \times 1\) 的砖不能少于 \(C\) 块也不能多于 \(D\) 块, \(1 \times 2\) 的砖没有数量限制. 有些方格在一开始就已经被填充了,