• 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;
    }
    
  • 相关阅读:
    《黑天鹅》笔记
    《随机漫步的傻瓜》笔记
    《眨眼之间》笔记
    《陌生人效应》笔记
    《设计心理学 -- 设计未来》笔记
    《设计心理学 -- 设计情感化》笔记
    《设计心理学 -- 与复杂共处》笔记
    《引爆点》笔记
    《逆转》笔记
    《设计心理学 -- 日常的设计》笔记
  • 原文地址:https://www.cnblogs.com/tomori/p/13715206.html
Copyright © 2020-2023  润新知