• POJ 2411 Mondriaan's Dream 状压dp


    题目链接:

    https://vjudge.net/contest/159644#problem/G

    题意:

    用1*2的砖去恰好铺满n*m的空间,有多少种方法

    题解:

    http://blog.csdn.net/xingyeyongheng/article/details/21692655

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 #define MS(a) memset(a,0,sizeof(a))
     7 #define MP make_pair
     8 #define PB push_back
     9 const int INF = 0x3f3f3f3f;
    10 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    11 inline ll read(){
    12     ll x=0,f=1;char ch=getchar();
    13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 //////////////////////////////////////////////////////////////////////////
    18 const int maxn = (1<<11)+10;
    19 
    20 int n,m;
    21 ll cnt[maxn],dp[maxn];
    22 bool mark[maxn];
    23 
    24 bool check(int x){
    25     while(x){
    26         if(x&1){
    27             x >>= 1;
    28             if(!(x&1)) return false;
    29             x >>= 1;
    30         }else {
    31             x >>= 1;
    32         }
    33     }
    34     return true;
    35 }
    36 
    37 void init(){
    38     MS(mark); MS(cnt);
    39     for(int i=0; i<(1<<m); i++){
    40         if(check(i))
    41             cnt[i]=1,mark[i]=true;
    42     }
    43 }
    44 
    45 void DP(){
    46     for(int k=2; k<=n; k++){
    47         MS(dp);
    48         for(int i=0; i<(1<<m); i++){ // 枚举本行的状态
    49             for(int j=0; j<(1<<m); j++){  // 枚举上一行的状态,找到可以转移到第i行的状态
    50                 if((i|j) != (1<<m)-1) continue;
    51                 if(!mark[i&j]) continue;
    52                 dp[i] += cnt[j]; //i可以从j到达,则增加j的方案数
    53 // mark[i&j] 是为了判断两行都是横着放的状态--->  1 1
    54 //                                               1 1
    55 // 如果是 i = 00110011
    56 //        j = 11011111  i&j=00010011 这是不合法的
    57 
    58             }
    59         }
    60         for(int i=0; i<(1<<m); i++) cnt[i] = dp[i];
    61     }
    62 }
    63 
    64 int main(){
    65     while(cin>>n>>m && (n+m)){
    66         if(n<m) swap(n,m); //始终保持m<n,提高效率   
    67         init();
    68         DP();
    69 
    70         cout << cnt[(1<<m)-1] << endl; //输出最后一行到达时的状态必须全部是1
    71     }
    72 
    73     return 0;
    74 }
    75 // http://blog.csdn.net/xingyeyongheng/article/details/21692655
  • 相关阅读:
    [BZOJ2969] 矩形粉刷
    数字 (number)
    字符串(String)
    小HY的四元组
    最大公约数(Max Gcd)
    [洛谷P2102] 地砖铺设
    Python OS模块(内置模块)
    json解析神器--jsonpath
    kafka 优势+应用场景
    Python之异常处理
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827555.html
Copyright © 2020-2023  润新知