Uva 11270 Tiling Dominoes 轮廓线dp入门题

来源:互联网 发布:全自动微电影软件 编辑:程序博客网 时间:2024/04/19 22:40

Tiling Dominoes, Uva 11270, 轮廓线dp入门题

将n*m的网格分成n*m个阶段

每个阶段i*j有2^m个状态

dp[n][m][1<<m](m为min(m, n)) 这里用了滚动数组

对于每个阶段的每个状态有3种转移方式

(1)不放

(2)竖放

(3)横放

转移条件见注释

//#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <ctime>#include <cstdlib>#include <cstring>#include <queue>#include <string>#include <set>#include <stack>#include <map>#include <cmath>#include <vector>#include <iostream>#include <algorithm>using namespace std;#define FE(i, a, b) for(int i = (a); i <= (b); ++i)#define FD(i, b, a) for(int i = (b); i >= (a); --i)#define REP(i, N) for(int i = 0; i < (N); ++i)#define CLR(a, v) memset(a, v, sizeof(a))#define PB push_back#define MP make_pairtypedef long long LL;const int INF = 0x3f3f3f3f;LL dp[2][1 << 10];int now, next;int n, m;int ALL;void update(int b, int a)///now阶段的a状态,向next阶段的b状态转移{    if (b & (1 << m))///保证全部被覆盖的条件        dp[next][b ^ (1 << m)] += dp[now][a];}int main(){    while (scanf("%d%d", &n, &m) != EOF)    {        if (n < m) swap(n, m);        CLR(dp, 0);        now = 0;        ALL = (1 << m) - 1;        dp[0][ALL] = 1;        REP(i, n) REP(j, m)///枚举阶段i,j        {            next = now ^ 1;            for (int r = 0; r <= ALL; r++)///枚举当前阶段的状态            {                if (dp[now][r])                {                    update(r << 1, r);///不放                    if (i && !(r & (1 << (m - 1)))) update((r << 1) ^ (1 << m) ^ 1, r);///竖着放,要求,上面的ceil为没有覆盖且i不是第一行                    if (j && !(r & 1)) update((r << 1) ^ 3, r);///横着放,要求,左面的ceil为没有覆盖且j不是第一列                }            }            CLR(dp[now], 0);            now ^= 1;        }        printf("%lld\n", dp[now][ALL]);    }}