zoukankan      html  css  js  c++  java
  • ZOJ 2563 Long Dominoes(状压DP)题解

    题意:n*m的格子,用1 * 3的矩形正好填满它,矩形不能重叠,问有几种填法

    思路:poj2411进阶版。我们可以知道,当连续两行的摆法确定,那么接下来的一行也确定。当第一行还有空时,这时第三行必须要用3 * 1的去填;当第一行没有空第二行有空时,第三行必须不填;当第一行有空第二行没空,这种不能存在;当前两行没空时,我最多就是填1 * 3的方块。

    代码:

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include <iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 11 + 5;
    const int M = maxn * 30;
    const ull seed = 131;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e4 + 7;
    ll dp[31][1 << maxn];
    int fac[maxn];
    int vis[maxn];
    int n, m;
    int prest;
    //0:都是空的 1:上一个非空 2:都非空
    int getSt(){
        int ret = 0;
        for(int i = m - 1; i >= 0; i--)
            ret = ret * 3 + vis[i];
        return ret;
    }
    void dfs(int i, int j){
        if(j >= m){
            int st = getSt();
            dp[i][st] += dp[i - 1][prest];
            return;
        }
        int p = prest / fac[j] % 3;
        if(p == 0){
            vis[j] = 2;
            dfs(i, j + 1);
        }
        else if(p == 1){
            vis[j] = 0;
            dfs(i, j + 1);
        }
        else{
            if(j >= 2 && vis[j - 1] == 1 && vis[j - 2] == 1){
                vis[j] = vis[j - 1] = vis[j - 2] = 2;
                dfs(i, j + 1);
                vis[j] = vis[j - 1] = vis[j - 2] = 1;
            }
            vis[j] = 1;
            dfs(i, j + 1);
        }
    }
    int main(){
        fac[0] = 1;
        for(int i = 1; i <= 10; i++) fac[i] = fac[i - 1] * 3;
        while(~scanf("%d%d", &m, &n) && n + m){
            memset(dp, 0, sizeof(dp));
            dp[0][fac[m] - 1] = 1;
            for(int i = 1; i <= n; i++){
                for(int j = 0; j < fac[m]; j++){
                    if(dp[i - 1][j] == 0) continue;
                    memset(vis, 0, sizeof(vis));
                    prest = j;
                    dfs(i, 0);
                }
            }
            printf("%lld
    ", dp[n][fac[m] - 1]);
        }
        return 0;
    }
  • 相关阅读:
    POJ 1392 Ouroboros Snake 欧拉回路
    POJ 1275 Cashier Employment 差分约束+二分答案
    POJ 1780 Code 欧拉回路+手写栈DFS
    POJ 1300 Door Man 欧拉路的判断
    HDU1534 Schedule Problem 差分约束
    POJ 3169 Layout 差分约束
    POJ 1364 King 差分约束 找负环
    ZOJ 2770 Burn the Linked Camp 差分约束+SPFA
    Zoj 2027 Travelling Fee 最短路变形
    Poj 2263 Heavy Cargo Floyd 求最大容量路
  • 原文地址:https://www.cnblogs.com/KirinSB/p/10960808.html
Copyright © 2011-2022 走看看