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>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#define eps 1e-6
#define LL long long
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
//const int INF = 0x3f3f3f3f;
//freopen("input.txt", "r", stdin);
int n, m, cur;
const int maxn = 11;
LL d[2][1<<maxn];

int main() {
	while(scanf("%d%d", &n, &m) == 2) {
		if(m > n) swap(m, n);
		cur = 0;
		memset(d[cur], 0, sizeof(d[cur]));
		d[cur][(1<<m)-1] = 1;
		for(int i = 0; i < n; i++)
			for(int j = 0; j < m; j++) {
				cur ^= 1;
				memset(d[cur], 0, sizeof(d[cur]));
				for(int k = 0; k < (1<<m); k++) {
					if(k&(1<<(m-1))) d[cur][(k<<1)^(1<<m)] += d[1-cur][k]; //不放
					if(i && !(k&(1<<(m-1)))) d[cur][(k<<1)+1] += d[1-cur][k];
					if(j && !(k&1) && (k&(1<<(m-1)))) d[cur][(k<<1)^(1<<m)|3] += d[1-cur][k];
				}
			}
		LL ans = d[cur][(1<<m)-1];
		printf("%lld\n", ans);
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-23 20:49:50

UVA 11270 Tiling Dominoes(轮廓线DP经典)的相关文章

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

UVA 11270 Tiling Dominoes

https://vjudge.net/problem/UVA-11270 题目 用$1\times2$骨牌覆盖$n\times m$棋盘,有多少种方法? $n\times m<101$ 题解 棋盘已经填了的部分只能用考虑轮廓线表示清楚,不能只用行和列.轮廓线总共有$2^{宽}$种状态,因此需要把宽度尽量缩小. 令$n\leqslant m$,可以得到$n\leqslant 10$,所以轮廓线的状态有$2^{10}$种. 只在轮廓线的右下角放骨牌,并且保证轮廓线的上面是完全填满了的.比如下图这样的

【UVa】Tiling Dominoes

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2245 题意:求用1×2的棋子摆满n×m的棋盘的方案数.(n×m<=100) #include <bits/stdc++.h> using namespace std; long long d[2][1<<10], n, m; int main() { while

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

https://vjudge.net/problem/UVA-11270 题意: 用1×2骨牌覆盖n×m棋牌,有多少种方法? 思路: 这道题目是典型的轮廓线DP题. 所谓轮廓线DP,就是以整行整列为状态进行动态规划时无法进行状态转移,那么此时就可以用到轮廓线,当然,这种方法只能使用在一个窄棋盘上,大了肯定是不行的,要超时! ' 轮廓线DP就是按照从上到下,从左到右的顺序进行状态转移,每个格子用二进制来表示状态,1代表的就是覆盖,0代表未覆盖. 以本题为例,如上图,我们现在要计算 k 格子,那么与

POJ 3254 Corn Fields (状压DP,轮廓线DP)

题意: 有一个n*m的矩阵(0<n,m<=12),有部分的格子可种草,有部分不可种,问有多少种不同的种草方案(完全不种也可以算1种,对答案取模后输出)? 思路: 明显的状压DP啦,只是怎样压缩状态?跟轮廓线DP一样,按格子为单位来设计状态,一个状态只需要表示到其上方和左方的格子,所以最多只需要保存min(n,m)个01状态就行了(可以尝试旋转一下矩阵),最多需要12位.用哈希表来做会比较快吧,不用去考虑无效的状态,比如出现相邻两个1. 1 //#include <bits/stdc++.

轮廓线DP POJ3254

补了一发轮廓线DP,发现完全没有必要从右往左设置状态,自然一点: 5 6 7 8 9 1 2 3 4 如此设置轮廓线标号,转移的时候直接把当前j位改成0或者1就行了.注意多记录些信息对简化代码是很有帮助的,尤其对于我这种代码经常错的一塌糊涂的人来说.. 呆马: #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath>

uva 12186 Another Crisis 树形dp

// uva 12186 Another Crisis 树形dp // // 对于一个节点u,有k个子节点,则至少有c = (k * T - 1) / 100 + 1才能 // 发信,即c / k >= T / 100,则 c 的值为 k * T /100,上取整变成上式 // 将所有的子节点d从小到大排序,取前c个就是d[u]的值 // 紫书上的一题,之前看了好久好久,觉得挺好的,然而一直没做,今天就来 // 体验体验,挺好的一题,注意一下,如果一个节点是叶节点,直接return 1就好 //

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

UVA 1399 - Puzzle(AC自动机+DP)

UVA 1399 - Puzzle 题目链接 题意:给定一些字符串,求一个最长的不在包含这些子串的字符串,如果可以无限长输出No 思路:建ACM自动机,把不可走结点标记构造出来,然后在这个状态图上进行dp找出最长路径即可,至于无限长的情况,只要在dp前进行一次dfs判有没有环即可 代码: #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include &