zoukankan      html  css  js  c++  java
  • poj2411 Mondriaan's Dream[简单状压dp]

    $11*11$格子板上铺$1*2$地砖方案。以前做过?权当复习算了,毕竟以前学都是浅尝辄止的。。常规题,注意两个条件:上一行铺竖着的则这一行同一位一定要铺上竖的,这一行单独铺横的要求枚举集合中出现连续偶数个的1,预处理一下即可。注意数据及时reset。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<queue>
     7 #define dbg(x) cerr<<#x<<" = "<<x<<endl
     9 using namespace std;
    10 typedef long long ll;
    11 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
    12 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
    13 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    14 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    15 template<typename T>inline T read(T&x){
    16     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    17     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    18 }
    19 const int N=12;
    20 ll f[N][1<<N-1];
    21 int n,m,ful,g[1<<N-1];
    22 
    23 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
    24     for(register int i=0;i<(1<<11);++i){
    25         int cnt=0;
    26         for(register int j=0;j<11;++j){
    27             if(!((1<<j)&i)){if(cnt&1)break;cnt=0;}
    28             else ++cnt;
    29         }
    30         if(!(cnt&1))g[i]=1;
    31     }
    32     while(read(n),read(m),n){
    33         if((n*m)&1){printf("0
    ");continue;}
    34         f[0][ful]=0;ful=(1<<m)-1;f[0][ful]=1;
    35         for(register int i=1;i<=n;++i){
    36             for(register int j=0;j<=ful;++j){
    37                 f[i][j]=0;
    38                 for(register int k=0;k<=ful;++k)if(((j|k)==ful)&&(g[j&k])){
    39                     f[i][j]+=f[i-1][k];
    40                 }
    41             }
    42         }
    43         printf("%lld
    ",f[n][ful]);
    44     }
    45     return 0;
    46 }
    View Code

     UPD:以前个人理解这个$0/1$状态设计有问题。应当是$f[i][S]$表示的是当前推导了第$i$行,状态$S$,对应二进制位$1$的表示这一格填了,$0$表示还没填,有$0$的这种情况下是留作下一行使用的(也就是可以由现在没填的情况推向下一行同一列填好的情况),说“表示放下竖着摆的砖的上半部分”的说法是不确切的。这样,用上述正确的状态定义就可以方便解决绝大多数铺砖类题目。再比如:

    如果有的格子不准铺,有多少种铺法?最多铺多少个?用上面的定义,可以在当前状态$S$下使用DFS推导出下一行的所有合法方案并更新,不能铺的地方也用$1$来表示。当然,也可以使用轮廓线DP来推,但是好像会被dfs吊打。。但是最好不要用暴力枚举来推,有大量冗余状态。

    详细可以见这道题目题解。poj1038 Bugs Integrated, Inc.[状压DP]

  • 相关阅读:
    北京爱丽丝幻橙科技有限公司
    红杉资本中国基金:创业者背后的创业者
    关于我们_ | 腕表时代watchtimes.com.cn
    当你想放弃的时候,问一下自己你尽力了吗
    李圣杰_百度百科
    范思哲
    DOM Traversal Example | Documentation | Qt Project
    关于QT中evaluateJavaScript()函数返回值的处理问题
    JS获取整个HTML网页代码
    javascript
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10708695.html
Copyright © 2011-2022 走看看