zoukankan      html  css  js  c++  java
  • [題解/狀壓dp]POJ_2411_Mondriaan's dream

    关于“我读过很多书,到后来大部分都被我忘记了,那阅读的意义是什么?”的疑问,我看过最巧妙的一个回答:当我还是个孩子的时候,我吃过很多的食物,大部分已经一去不复返而且被我忘记了,但可以肯定的是,它们中的一部分已经成长为我的骨头和肉。阅读对你的思想的改变也是如此。


    填充的方法:

    每個點三種情況,

    1)是一個豎著的1*2的長方形的上半部分,對下一行限制是必須補全該長方形,用二進制1來表示

    2)是一個豎著的1*2的長方形的下半部分,對下一行無限制,用0表示

    3)是一個橫著的1*2的長方形的一部分,對下一行沒有限制,用0表示

    按行號dp,f [ i ] [ j ]表示第 i 行狀態為 j 的方案數,

    第 i-1 行的狀態 k 能轉移到第 i 行狀態為 j 當且僅當:

    1.j 和 k 執行按位与結果為0(保證每個數字1的下方必須是0)

    2.j 和 k 執行按位或結果每一段連續的0都必須有偶數個(若干橫著的1*2長方形)

    (按位或后就去掉了和上面一起成為一個長方形的情況)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int n,m;
    ll f[12][1<<11];
    bool b[1<<11];
    int main()
    {
        while(cin>>n>>m && n){
            //預處理出[0,1<<m-1]中所有每一段連續的0都有偶數個的數 
            for(int i=0;i< 1<<m;i++){
                bool cnt=0,has_odd=0;//cnt為這一段0個數的奇偶性,hasodd為是否為奇數 
                for(int j=0;j<m;j++)
                if(i>>j & 1)
                has_odd|=cnt,cnt=0;//第j位為1就重置,并記錄在hasodd里 
                else cnt^=1;//更新這一段奇偶性 
                b[i]=has_odd|cnt ? 0:1;//其中任何一個是1都不行 
            }
            f[0][0]=1;
            for(int i=1;i<=n;i++)
            for(int j=0;j< 1<<m;j++){//枚舉狀態 
                f[i][j]=0;//多組數據初始化 
                for(int k=0;k< 1<<m;k++)
                if((j&k)==0 && b[j|k])
                f[i][j]+=f[i-1][k];
            }
            printf("%lld
    ",f[n][0]);
        }
    }
  • 相关阅读:
    20200924-2 功能测试
    作业要求20200924-4 代码规范,结对要求
    20200924-1 每周例行报告
    20200929-git地址
    白名单
    作业要求 20200917-1 每周例行报告
    词频统计 SPEC
    20200910-1 每周例行报告
    20200924-3 单元测试,结对
    20200924-5 四则运算试题生成,结对
  • 原文地址:https://www.cnblogs.com/superminivan/p/10616996.html
Copyright © 2011-2022 走看看