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;
    }
  • 相关阅读:
    做题记录
    关于有向图强连通分量的一点想法
    浅谈二分图匹配(未完)
    水题狂欢赛 (爬楼梯赛)题解(偏向自我反省)
    浅谈迭代加深(iddfs)
    浅谈单调队列优化
    [cqbzoj#10644]鱼肉炸弹题解
    树形背包[2/ 50] luogu [P1273]
    树形背包[1/ 50] luogu [P2015] (超级板)
    (树状数组)区间修改,区间查询
  • 原文地址:https://www.cnblogs.com/KirinSB/p/10960808.html
Copyright © 2011-2022 走看看