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

    题目:http://poj.org/problem?id=2411

    Input

    The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.

    Output


    For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.

    题意:一个矩阵,只能放1*2的木块,问将这个矩阵完全覆盖的不同放法有多少种。

    思路:一道很经典的状态dp,但是还是很难想,横着放定义为11,竖着放定义为01.

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 using namespace std;
     6 __int64 d[12][1<<12], f[1<<12];//用———int64,因为有可能数很大
     7 int h, w, full;
     8 
     9 bool ok(int x) //判断一行里是否出现连续奇数个1,第一行的话不允许
    10 {
    11     int sum = 0;
    12     while(x>0)
    13     {
    14         if((x&1)==1)
    15         sum++;
    16         else
    17         {
    18             if((sum&1)==1)
    19             return false;
    20             sum = 0;
    21         }
    22         x = (x>>1);
    23     }
    24     if((sum&1)==1)
    25             return false;
    26     return true;
    27 }
    28 bool check(int x1, int x2)
    29 {
    30     int xx = (1<<w)-1;
    31     if((x1|x2)==xx&&f[x1&x2])//去掉竖着00和竖着单独11的情况,一定不要忘了单独11的情况
    32     return true;
    33     return false;
    34 }
    35 int main()
    36 {
    37     int i, j, k;
    38     memset(f, 0, sizeof(f));
    39     full = (1<<11);
    40 
    41     for(i = 0; i < full; i++)
    42     if(ok(i))
    43     f[i] = 1;   //记录连续的奇数个1
    44     while(~scanf("%d%d", &h, &w))
    45     {
    46         if(h==0&&w==0)
    47         break;
    48         full = (1<<w);
    49         memset(d, 0, sizeof(d));
    50         for(i = 0; i < full; i++)
    51         if(f[i])
    52         d[0][i] = 1;
    53 
    54         for(k = 1; k < h; k++)
    55         for(i = 0; i < full; i++)
    56         for(j = 0; j < full; j++)
    57         {
    58             if(check(i, j))
    59             d[k][i] += d[k-1][j];
    60         }
    61         printf("%I64d
    ", d[h-1][full-1]); //最后一行,而且满1
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/bfshm/p/3585598.html
Copyright © 2011-2022 走看看