zoukankan      html  css  js  c++  java
  • poj 2411 Mondriaan's Dream 状态压缩DP 打表

      将题目转换题意, 有一个M列的墙, 我们需要 使用 1*2 的小矩形 砌成N层高, 有多少不同的方案数量.

      因为只有1*2的砖头, 且只有竖立或者横着放.

      那么我们规定 竖立放置的砖头属于 较高的一层, 且 当前点放置砖头则为1,否则为0

      那么我们可以得出结论:

      对于 I 层 状态 X , 若当前位置为0,则下层必定为1. 则意味着下层必定包含 t = (~X)& Mask 

      对于 I+1 层 状态 Y, 除了包含 状态 t 之外, 剩下标记为1的 必须两两成对.才可符合状态.

      

      注意   t = (~X)& Mask    这里要记得还要与 总集合MASK相与. 把状态限定在MASK之内

    解题代码:

    View Code
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    typedef long long LL;
    typedef unsigned int uint;
    const int N = 1<<11;
    /*
    计算结果代码部分
    LL ans[12][12];
    
    LL dp[12][N+10];
    int n, m;
    
    bool check( uint x ){
        
        for(uint i = 0; i < m; i++)
        {
            if( x&(1<<i) )
            {
                if( i+1 >= m ) return false;
                if( ( x&(1<<(i+1) ) ) == 0 ) return false;
                i++;
            }
        }
        return true;
    }
    
    int main()
    {
        freopen("6.out","w",stdout);
    
        memset( ans, 0, sizeof(ans) );
        for(n = 1; n <= 11; n++)
            for(m = 1; m <= 11; m++)
        {
            memset( dp, 0, sizeof(dp) );
        
            int Max = (1<<m)-1;
            for(int mask = 0; mask <= Max; mask++)
                if( check(mask) ) dp[0][mask] = 1;
        
        //    for(uint i = 0; i < Max; i++)
        //        if( dp[0][i] ) printf("%d ", i); puts("");
        
            for(int h = 0; h < n-1; h++)
            {
                for(uint mask = 0; mask <= Max; mask++)
                {
                    if( dp[h][mask] ){
                        uint t = (~mask)&Max;
                        for(uint x = 0; x <= Max; x++)
                        {
                    //        printf("mask = %u, t = %u, x = %u\n", mask, t, x );    
                            if( ((x&t)==t) && check( t^x ) ) 
                                dp[h+1][x] += dp[h][mask];    
                        
                        }    
                    }    
                }
        //        cur = !cur;    
            }
        //    printf( (n==1&&m==1) ? "%lld" : ",%lld", dp[n-1][Max] );    
            ans[n][m] = dp[n-1][Max];
        }
        printf("{\n");
        for(int i = 0; i <= 11; i++)
        {
            printf("{");    
            for(int j = 0; j <= 11; j++)
            {
                printf( j == 0 ? "%lld" : ",%lld", ans[i][j] );    
            }
            printf( i == 11 ? "}\n" :  "},\n");        
        }
        printf("};\n");    
        return 0;
    }
    */
    LL ans[12][12] =
    {
    {0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,1,0,1,0,1,0,1,0,1,0},
    {0,1,2,3,5,8,13,21,34,55,89,144},
    {0,0,3,0,11,0,41,0,153,0,571,0},
    {0,1,5,11,36,95,281,781,2245,6336,18061,51205},
    {0,0,8,0,95,0,1183,0,14824,0,185921,0},
    {0,1,13,41,281,1183,6728,31529,167089,817991,4213133,21001799},
    {0,0,21,0,781,0,31529,0,1292697,0,53175517,0},
    {0,1,34,153,2245,14824,167089,1292697,12988816,108435745,1031151241,8940739824},
    {0,0,55,0,6336,0,817991,0,108435745,0,14479521761,0},
    {0,1,89,571,18061,185921,4213133,53175517,1031151241,14479521761,258584046368,3852472573499},
    {0,0,144,0,51205,0,21001799,0,8940739824,0,3852472573499,0}
    };
    
    int main()
    {
        int n, m;
        while( scanf("%d%d",&n,&m) != EOF)
        {
            if(n+m == 0 ) break;
            printf("%lld\n", ans[n][m]);
        }
        return 0;
    }
  • 相关阅读:
    .NET 使用EF执行存储过程你知道几种?
    SQLserver 如何优雅的行转列
    SQLserver 如何获取近1月、近3个月、近6月数据
    三汇自动挂断问题:SIP兼容性,ACK检测,忽略ACK开启。
    几个flutter 开源项目测试
    Android versions for all users globally
    Using Flutter 2 on M1 MacOS Apple Silicon
    Educational Codeforces Round 111
    Wannafly挑战赛1
    摆烂记录
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2852643.html
Copyright © 2011-2022 走看看