• POJ 2411 Mondriaan's Dream/[二进制状压DP]


    题目链接【http://poj.org/problem?id=2411】

    题意:给出一个h*w的矩形1<=h,w<=11.用1*2和2*1的小矩形去填满这个h*w的矩形,问有多少种方案数?

    题解:用0、1表示矩形中每个位置的状态,0表示没有被铺上木块,1表示已经被铺上木块,把每一行的状态看成是一个二进制数,用十进制表示。

    每一行的总状态为[0,(1<<w)-1];dp[i][j]表示第i行,状态为j,并且i行以上都被填满了的总方案数。

    因为r行的状态只和r-1排的状态有关,可以用滚动数组实现。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn = 1 << 12;
    LL dp[2][maxn];
    int n, m;
    int cur;
    void DFS(int pos, int nu, int z)
    {
        if(pos == m)//处理第m个位置的时候本行已经处理完了
        {
            dp[cur][nu] += dp[cur ^ 1][z];
            return ;
        }
        if(!(z & (1 << pos)))//如果上一行的pos位置是0,那么本行的pos位置必须是竖着放
            DFS(pos + 1, nu | (1 << pos), z);
        else
        {
            if(pos && (!(nu & (1 << pos - 1))))//判断是否可以横着放
                DFS(pos + 1, nu | (1 << pos) | (1 << pos - 1), z);
            DFS(pos + 1, nu, z);//不放木块,留着下一排去解决。
        }
    }
    int main ()
    {
        while(~scanf("%d%d", &n, &m))
        {
            if(n == 0 && m == 0)
                break;
            cur = 0;
            int mask = (1 << m) - 1;//可能的状态总数
            memset(dp, 0, sizeof(dp));
            dp[0][mask] = 1;//第一排的有效状态是mask
            for(int i = 1; i <= n; i++)
            {
                cur ^= 1;
                memset(dp[cur], 0, sizeof(dp[cur]));
                for(int j = 0; j <= mask; j++)
                    if(dp[cur ^ 1][j])
                        DFS(0, 0, j);
            }
            printf("%lld
    ", dp[cur][mask]);
        }
        return 0;
    }

      

    想的太多,做的太少。
  • 相关阅读:
    AVR单片机教程——PWM调光
    AVR单片机教程——蜂鸣器
    AVR单片机教程——串口接收
    做个别出心裁的圣诞礼物
    电源选择电路的原理
    AVR单片机教程——串口发送
    C++类成员默认初始值
    AVR单片机教程——旋转编码器
    10.Django-form表单
    09.Django-数据库优化
  • 原文地址:https://www.cnblogs.com/pealicx/p/6234661.html
Copyright © 2020-2023  润新知