zoukankan      html  css  js  c++  java
  • Mondriaan's Dream

    Mondriaan's Dream

    有一个(n imes m)的网格图,用(1 imes 2)的矩形网格无重叠的摆满的方案数,(1leq n,m leq 11)

    数据范围已经提示可以二进制压缩,考虑到网格图常以行列为阶段,所以自然想到(dp[i][j])表示处理到第i行,第i行的状态为j的方案数。

    而对于状态j的解释,最自然的是其中1表示一个竖着的网格,但是注意这样并不能保证竖着的矩形长度正好为2,所以设1为此处为矩形的上半,注意到要保证一行的合法性,我们的保证竖着的矩形之间有偶数个网格,而这个我们可以预处理,设(a[i])表示状态i是否合法,于是我们有

    [dp[i][j]=sum_{k=0}^{2^m-1}dp[i-1][k](!k&j&&a[k|j]) ]

    边界:(dp[1][i]=1,i=1,2,3,...,2^m-1(a[i]))

    答案:(sum_{i=0}^{2^m-1}dp[n][i])

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    #define ll long long
    using namespace std;
    ll dp[12][2048];
    bool check[2048];
    int main(){
        int h,w,li;
        while(scanf("%d%d",&h,&w),h&&w){
            li=(1<<w)-1,memset(dp,0,sizeof(dp));
            memset(check,0,sizeof(check));
            for(ri int i(0),j,k;i<=li;++i){
                for(j=k=0;j<w;++j)
                    if(i>>j&1){if(k&1)break;k&=0;}
                    else k^=true;
                if(j==w&&!k)check[i]|=true,dp[1][i]=1;
            }
            for(ri int i(2),j,k;i<=h;++i)
                for(j=0;j<=li;++j)
                    for(k=0;k<=li;++k)
                        if(!(j&k)&&check[j|k])
                            dp[i][j]+=dp[i-1][k];
            printf("%lld
    ",dp[h][0]);
        }
        return 0;
    }
    
    
  • 相关阅读:
    ubuntu防火墙设置通过某端口
    pandas入门
    pyplot入门
    numpy教程
    跨域请求 spring boot
    spring boot 启动流程
    代理配置访问
    AOP,拦截器
    spring boot 启动不连接数据库
    Python 3.x 连接数据库(pymysql 方式)
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10940234.html
Copyright © 2011-2022 走看看