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

    状压dp的一种经典模型,覆盖问题。

    我们定义f[i][j]表示当第i行的状态为j时,前i行的方案数。显然答案为f[n][0].

    关于压缩状态,我们定义一个m位的二进制数,其中第i位为1的含义是,第i列是一个竖着的矩形的上半部分。第i位为0则表示其他情况。

    因此,第i-1行的状态k能转移到第i行的状态j,当且仅当:

    1. k&j的值为0.这保证了每一个1下面都是0。代表继续补全这个矩形。
    2. j|k的结果的二进制表示中,每一段连续的0都必须有偶数个。因为这些0表示横躺着的矩形,当为奇数时不符合题意。(我们预处理符合题意的情况记录在集合S中)

    写成公式就是

    因此,我们可以在dp之前预处理出每一种状态是否符合条件2即可实现O(1)的转移,总时间复杂度为O(4mn).

     1 #include <iostream>
     2 using namespace std;
     3 int n,m;
     4 long long f[12][1<<12];
     5 bool ok[1<<12];
     6 int main() {
     7     while(cin>>n>>m&&n+m) {
     8         for(int i=0;i<1<<m;i++) {
     9             bool pd=0,x=0; 
    10             for(int j=0;j<m;j++)
    11                 if(i>>j&1) pd|=x,x=0;
    12                 else x^=1;
    13             ok[i]=x|pd?0:1;
    14         }
    15         f[0][0]=1;
    16         for(int i=1;i<=n;i++)
    17             for(int j=0;j<1<<m;j++) {
    18                 f[i][j]=0;
    19                 for(int k=0;k<1<<m;k++)
    20                     if(!(k&j)&&ok[j|k]) f[i][j]+=f[i-1][k];
    21             }
    22         printf("%lld
    ",f[n][0]);
    23     }
    24     return 0;
    25 }
    AC Code
  • 相关阅读:
    U1. 广度优先搜索(BFS)和 广度优先搜索(DFS)
    C5. Spring 服务的注册与发现(Spring Cloud Eureka)
    S3. Android 消息推送
    S2. Android 常用控件
    S12. Android 检查更新功能实现
    S1. Android 功能大全
    B9 Concurrent 重入锁(ReentrantLock)
    117.dom2事件
    106.事件的传播机制
    105.事件对象及兼容处理
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10701262.html
Copyright © 2011-2022 走看看