[ACM] HDU 1400 Mondriaan's Dream (狀態壓縮,長2寬1長方形鋪滿)

來源:互聯網
上載者:User

標籤:acm   狀態壓縮   

Mondriaan‘s Dream

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 783    Accepted Submission(s): 506


Problem Description

 

Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his ‘toilet series‘ (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways. 



Expert as he was in this material, he saw at a glance that he‘ll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won‘t turn into a nightmare! 


 


 

Input

 

The input file 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.
 


 

Sample Input

 

1 21 31 42 22 32 42 114 110 0
 


 

Sample Output

 

10123514451205
 


 

Source

 

University of Ulm Local Contest 2000

 

解題思路:

問鋪滿大舉行一共有多少種方法。因為長寬最大11,可以狀態壓縮.

從第一行開始鋪磚。

dp[ i ]  [ j ] 定義為 第i行的狀態為 j 一共有多少種方法 .

把小矩形用01狀態表示,小矩形由兩個正方形組成, 對於橫著放的小矩形,左右兩個正方形用11表示,對於豎著的小矩形,上下兩個正方形用分別01表示。

第i行的狀態s2與第i-1行的狀態s1有關。

s1和s2滿足兩個條件:

1.   s1  |  s2  得到的數二進位每一位都是1 ,因為對於豎著放的 ,0|1肯定是1,橫著放的都是11,相或也是11.

2.   s1  & s2  得到的數連續的1是偶數個,注意0也是偶數。這個看圖觀察就可以了。

 

本題犯的錯誤:

1.

擷取一個數x二進位的第i位是0或者1,用 if( x&(1<<i) ==1) 是不對的, 這句話的意思是,把x的位元除了第i位都設為0,第i位通過 &1,來判斷是0或者1,但是得到的數不一定是1,是2的倍數,比如 0010  或者 0100.

2.

判斷一個數x二進位的每一位是否等於1 ,假設有m位 , 直接用 if( x==1<<m)-1),不用每一位的判斷,前者效率更高。

代碼:

 

#include <iostream>#include <stdlib.h>#include <stdio.h>#include <vector>#include <algorithm>#include <string.h>using namespace std;#define ll long longll dp[12][1<<12];//dp[i][j]表示第i行狀態為j有多少種方法int n,m;bool ok(int s1,int s2){    int temp=s1|s2;//兩個狀態或運算每一位都必須是1    if(temp!=(1<<m)-1)        return false;    int cnt=0;    temp=s1&s2;//兩個狀態且運算,必須連續的1都是偶數個    for(int i=0;i<m;i++)    {        if((temp&(1<<i)))//第i位是1            cnt++;        else        {            if(cnt&1)                return false;        }    }    if(cnt&1)        return false;    return true;}void solve(){    memset(dp,0,sizeof(dp));    int maxd=1<<m;    for(int i=0;i<maxd;i++)//鋪第一行        if(ok(maxd-1,i))            dp[1][i]++;    for(int i=2;i<=n;i++)//鋪第i行    {        for(int j=0;j<maxd;j++)        {            for(int k=0;k<maxd;k++)                if(ok(j,k))                    dp[i][j]+=dp[i-1][k];        }    }    ll ans=0;    ans+=dp[n][maxd-1];//最後一行肯定都是1    printf("%I64d\n",ans);}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        if(!n||!m)            break;        if(n*m&1)//小方塊的個數為奇數個,肯定不能鋪滿        {            printf("0\n");            continue;        }        if(n<m)            n=n^m,m=n^m,n=n^m;        solve();    }    return 0;}


 

 

[ACM] HDU 1400 Mondriaan's Dream (狀態壓縮,長2寬1長方形鋪滿)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.