zoukankan      html  css  js  c++  java
  • Solid Dominoes Tilings (轮廓线dp打表 + 容器)

    第一步先打一个表,就是利用轮廓线DP去打一个没有管有没有分界线组合数量的表

    #include<bits/stdc++.h>
    using namespace std;
    
    const int mod = 1e9 + 7;
    const int maxn = 1<<17;
    int dp[2][maxn + 7];
    int ans[20][20];
    
    int solve(int n, int m){
        if(n * m % 2 == 1) return 0;
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        int ing = 0, ed = 1;
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < m; j ++){
                swap(ing, ed);
                memset(dp[ing], 0, sizeof(dp[ing]));
                for(int sta = 0; sta < (1<<m); sta ++){
                    if(sta & (1<<j)) dp[ing][sta&(~(1<<j))] = (dp[ing][sta&(~(1<<j))] + dp[ed][sta]) % mod;//无添加
                    if((sta & (1<<j)) == 0) dp[ing][sta | (1<<j)] = (dp[ing][sta | (1<<j)] + dp[ed][sta]) % mod;//加上2*1(竖放)
                    if(((sta & (3<<j)) == 0) && (j != m - 1)) dp[ing][sta | (1<<(j+1))] = (dp[ing][sta | (1<<(j+1))] + dp[ed][sta]) % mod;//加上1*2(横放)
                }
            }
        }
        return dp[ing][0];
    }
    
    int main(){
        freopen("data.txt", "w", stdout);
        for(int i = 1; i < 17; i ++)
            for(int j = 1; j < 17; j ++)
                ans[i][j] = solve(i, j);
        for(int i = 0; i < 17; i ++){
            for(int j = 0; j < 17; j ++)printf("%d, ",ans[i][j]);
        }
        return 0;
    }

    然后用容器原理加上枚举列当前分界线情况去递推容斥。具体如代码:

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const LL mod=1e9+7;
    
    LL dp[17][17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,0,0,3,0,11,0,41,0,153,0,571,0,2131,0,7953,0,29681,0,1,5,11,36,95,281,781,2245,6336,18061,51205,145601,413351,1174500,3335651,9475901,0,0,8,0,95,0,1183,0,14824,0,185921,0,2332097,0,29253160,0,366944287,0,1,13,41,281,1183,6728,31529,167089,817991,4213133,21001799,106912793,536948224,720246619,704300462,289288426,0,0,21,0,781,0,31529,0,1292697,0,53175517,0,188978103,0,124166811,0,708175999,0,1,34,153,2245,14824,167089,1292697,12988816,108435745,31151234,940739768,741005255,164248716,498190405,200052235,282756494,0,0,55,0,6336,0,817991,0,108435745,0,479521663,0,528655152,0,764896039,0,416579196,0,1,89,571,18061,185921,4213133,53175517,31151234,479521663,584044562,472546535,732130620,186229290,274787842,732073997,320338127,0,0,144,0,51205,0,21001799,0,940739768,0,472546535,0,177126748,0,513673802,0,881924366,0,1,233,2131,145601,2332097,106912793,188978103,741005255,528655152,732130620,177126748,150536661,389322891,371114062,65334618,119004311,0,0,377,0,413351,0,536948224,0,164248716,0,186229290,0,389322891,0,351258337,0,144590622,0,1,610,7953,1174500,29253160,720246619,124166811,498190405,764896039,274787842,513673802,371114062,351258337,722065660,236847118,451896972,0,0,987,0,3335651,0,704300462,0,200052235,0,732073997,0,65334618,0,236847118,0,974417347,0,1,1597,29681,9475901,366944287,289288426,708175999,282756494,416579196,320338127,881924366,119004311,144590622,451896972,974417347,378503901};
    LL f[17];
    int b[20],cnt,siz,n,m;
    LL solve(int n,int m){
        LL ret = 0;
        for(int sta = 0; sta < (1 << (m - 1)); sta ++){
            int cnt = 0, len = 0;
            for(int i = 0; i < m - 1; i ++){
                len ++;
                if(sta >> i & 1){
                    b[cnt ++] = len;
                    len = 0;
                }
            }
            b[cnt ++] =  ++len;
    
            for(int i = 1; i <= n; i ++){
                for(int j = 0; j < i; j ++){
                    LL temp = 1;
                    for(int k = 0; k < cnt; k ++)
                        temp = temp * dp[b[k]][i - j] % mod;
                    if(!j) f[i] = temp;
                    else f[i] = ( (f[i] - f[j] * temp % mod) % mod + mod ) % mod;
                }
            }
            if(!(cnt&1)) ret = ( (ret - f[n]) % mod + mod ) % mod;
            else ret = (ret + f[n]) % mod;
        }
        return ret;
    }
    int main(){
        while(~scanf("%d%d",&n,&m)) printf("%lld
    ",solve(n,m));
        return 0;
    }
    more crazy more get!
  • 相关阅读:
    lambda表达式
    解读Raft(一 算法基础)
    译《Time, Clocks, and the Ordering of Events in a Distributed System》
    如何在MQ中实现支持任意延迟的消息?
    读Kafka Consumer源码
    2017上海QCon之旅总结(下)
    2017上海QCon之旅总结(中)
    2017上海QCon之旅总结(上)
    什么是WAL?
    Push or Pull?
  • 原文地址:https://www.cnblogs.com/wethura/p/9737155.html
Copyright © 2011-2022 走看看