zoukankan      html  css  js  c++  java
  • poj 2411 Mondriaan's Dream(压缩状态dp)

    以前做过一道给定高度,然后给出长度让你求拼凑的方法的题,记得是到递推的题,如果这题不是在dp的训练计划里,我一定会耐心的去推公式的。呃,汗.......

    好吧,来说说这题吧。

    题意:给出矩形的长和高,然后让你计算用1*2或2*1的小矩形拼凑这个矩形,共有多少种方法?

    思路:刚才说了,开始我是想推公式来着,然后看了discuss了的一些讨论,才有了点想法,不过思路不是自己的,就不写了,个人觉得,下面这篇日志里讲的就很详细了~

    http://blog.csdn.net/wmn_wmn/article/details/7773167

    不过我觉得这题难的不是思路,而是关于二进制位运算的部分,如果不是很了解位运算的话,很难看懂代码的。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #define  N 12
    using namespace std ;
    
    typedef long long ll ;
    
    ll dp[N][1<<N] ;
    ll st[1<<N] ;
    int h , w ;
    
    int ok ( int x )
    {
        int i = 0 ;
        while( i < w )
        {
            if ( x & ( 1 << i ))
            i++ ;
            else
            {
                if( x & ( 1 << ( i + 1 )))
                return 0 ;
                if ( i == w - 1 )
                return 0 ;
                i += 2 ;
            }
        }
        return 1 ;
    }
    
    int main()
    {
        int i , j , k ;
    
        while( scanf( "%d%d" , &h , &w ) != EOF )
        {
            if ( h == 0 && w == 0 )
            break;
    
            if ( h % 2 && w % 2 )
            {
                printf ( "0\n" ) ;
                continue ;
            }
    
            memset( dp , 0 , sizeof ( dp ));
            if ( h < w )
            {
                int tem = h ;
                h = w ;
                w = tem ;
            }
            //初始化。
            int num = 0 ;
            for ( i = 0 ; i < ( 1<<w ) ; i++ )
            {
                if ( ok ( i ))
                {
                    dp[0][i] = 1 ;
                    st[num++] = i ;
                }
            }
            
            //修改每行的状态
            for ( i = 1 ; i < h ; i++ )
            {
                for ( j = 0 ; j < num ; j++ )
                {
                    for ( k = 0 ; k < ( 1<<w ) ; k++ )
                    {
                        if ( ( st[j] & k ) != k )
                        continue ;
                        dp[i][st[j]^k] += dp[i-1][k] ;
                    }
                }
            }
            cout<<dp[h-1][0]<<endl;
        }
        return 0 ;
    }
  • 相关阅读:
    递归 迷宫问题
    中缀表达式转后缀表达式
    栈实现后缀表达式计算

    单向环形链表
    站在巨人的肩上
    C#自宿主API,不依赖IIS
    MySQL 安装失败解决办法
    第一话
    村上春树《眠》读书笔记
  • 原文地址:https://www.cnblogs.com/misty1/p/2636422.html
Copyright © 2011-2022 走看看