zoukankan      html  css  js  c++  java
  • Mondriaan's Dream 题解(棋盘状压问题)

    题目链接

    题目大意

    现在有一个 n×m 的方格棋盘,和无限的 1×2 的骨牌。

    问有多少种方法可以用骨牌铺满棋盘。1 ≤ n,m ≤ 11

    题目思路

    这种算是状压dp的模板题目

    主要是思考上一行和这一行的转移即可

    需要两个连续的空位,并且上一行的这两个位置也得已经被覆盖。
    如果竖着:
    (a) 上一行对应的位置是空的,我们把那个空填上。

    (b) 上一行对应的位置是被覆盖的,那么我们把这一行的位置设为空,表示下一行的对应位置必须竖放,填上这块空白。

    运行dfs预处理所有状态即可

    代码

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,m;
    int tot=0;
    int from[maxn],to[maxn];
    ll dp[15][1<<12];
    void dfs(int d,int pre,int now){
        if(d>m) return ;
        if(d==m){
            ++tot;
            from[tot]=pre;
            to[tot]=now;
        }
        dfs(d+2,pre<<2|3,now<<2|3);
        dfs(d+1,pre<<1,now<<1|1);
        dfs(d+1,pre<<1|1,now<<1);
    }
    signed main(){
        while(scanf("%d%d",&n,&m)!=-1&&(n+m)){
            memset(dp,0,sizeof(dp));
            tot=0;
            dfs(0,0,0);
            dp[0][(1<<m)-1]=1;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=tot;j++){
                    dp[i][to[j]]+=dp[i-1][from[j]];
                }
            }
            printf("%lld
    ",dp[n][(1<<m)-1]);
        }
        return 0;
    }
    
    
    卷也卷不过,躺又躺不平
  • 相关阅读:
    redisLock redis分布式锁
    Mabitis中的#与$符号区别及用法介绍
    pring Scheduler定时器原理分析
    SpringBoot几种定时任务
    线程池的理解
    JVM的方法区和永久带是什么关系
    JVM老年代和新生代的比例
    IO 与 NIO
    对mysql乐观锁、悲观锁、共享锁、排它锁、行锁、表锁概念的理解
    TCP滑动窗口控制流量的原理
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15177814.html
Copyright © 2011-2022 走看看