zoukankan      html  css  js  c++  java
  • 291. 蒙德里安的梦想

    (f(i, j))表示在我摆放第i列的时候,i - 1列1*2方格伸出来的情况为j的所有摆法的集合,存储摆法数量
    (f(i, j) = D), D是所有满足以下两个条件的其他状态的集合中存储数量的和

    1. 从i - 2列伸出来的方格情况k和i - 1列伸出来的方格的情况之间没有冲突(k & j == 0)
    2. 从i - 2列伸出来的方格情况和i - 1列伸出来的方格情况合起来对第i列的影响要求第i列不存在奇数个空格(j | k中不存在奇数个0),这个可以预处理出来

    在满足条件1、2下,(f(i, j) = sum(f(i - 1, k)))

    其中j的范围:(0—2^n - 1), n为行数
    i的范围为1~m
    实际的列号范围为0~m - 1

    最终答案(f(0, m)),摆放到最后一列的后一列,并且最后一列(m - 1列)没有方格伸出来的所有情况

    #include<iostream>
    #include<cstring>
    
    using namespace std;
    
    const int N = 12, M = 1 << N;
    long long f[N][M];
    int st[M];
    int n, m;
    
    int main(){
        while(cin >> n >> m, m || n){
            
            memset(f, 0, sizeof f);
            
            //对于每一个0~1<<n - 1的所有二进制数,预处理出它是否含有奇数个0
            for(int i = 0; i < 1 << n; i ++){
                st[i] = 1;
                int cnt = 0;
                for(int j = 0; j < n; j ++)
                    if(i >> j & 1){
                        if(cnt & 1) st[i] = 0;
                        cnt = 0;
                    }else cnt ++;
                    
                if(cnt & 1) st[i] = 0;
            }
            
            f[0][0] = 1;
            
            for(int i = 1; i <= m; i ++)
                for(int j = 0; j < 1 << n; j ++)
                    for(int k = 0; k < 1 << n; k ++)
                        if((j & k) == 0 && st[j | k])
                            f[i][j] += f[i - 1][k];
                            
            
            cout << f[m][0] << endl;
        }
        
        return 0;
    }
    
  • 相关阅读:
    boost 1.49在vs 2005下编译的方法
    Mathematics for Computer Graphics
    字符串和字符数组长度
    四个月的学习心得
    话说stm32f10x-FSMC的配置与频率
    一些笔试题,大家都来围观呀~
    简单的生产者消费者-(windows下)
    STM32f10x下软件模拟IIc读写si5326问题
    usb枚举阶段(转载)
    STM32 GPIOB_PIN3复用功能小分析
  • 原文地址:https://www.cnblogs.com/tomori/p/13715206.html
Copyright © 2011-2022 走看看