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 }
  • 相关阅读:
    codeforces 820 D. Mister B and PR Shifts(思维)
    codeforces 820 C. Mister B and Boring Game(找规律)
    玲珑杯 1137
    codeforces 817 D. Imbalanced Array(单调栈+思维)
    Atcoder D
    Atcoder C
    Atcode B
    codeforces 816 E. Karen and Supermarket(树形dp)
    codeforces 816 D. Karen and Test(逆元+思维+组合数)
    codeforces 816 C. Karen and Game(模拟+思维)
  • 原文地址:https://www.cnblogs.com/bfshm/p/3585598.html
Copyright © 2011-2022 走看看