HDU 1992Tiling a Grid With Dominoes(狀壓dp)

果7發表於2014-03-26

Tiling a Grid With Dominoes

Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 410    Accepted Submission(s): 321


Problem Description
We wish to tile a grid 4 units high and N units long with rectangles (dominoes) 2 units by one unit (in either orientation). For example, the figure shows the five different ways that a grid 4 units high and 2 units wide may be tiled.



Write a program that takes as input the width, W, of the grid and outputs the number of different ways to tile a 4-by-W grid.
 

Input
The first line of input contains a single integer N, (1 ≤ N ≤ 1000) which is the number of datasets that follow.
Each dataset contains a single decimal integer, the width, W, of the grid for this problem instance.
 

Output
For each problem instance, there is one line of output: The problem instance number as a decimal integer (start counting at one), a single space and the number of tilings of a 4-by-W grid. The values of W will be chosen so the count will fit in a 32-bit integer.
 

Sample Input
3 2 3 7
 

Sample Output
1 5 2 11 3 781
 

Source
 

Recommend
linle   |   We have carefully selected several similar problems for you:  1988 1993 1985 1986 1987 
 


題目大意:題目意思是有一塊4*N(1 ≤ N ≤ 1000)實際上n不會超過21的空地。你只有1*2的磚。問你鋪滿這塊區域有多少種方法。

    解題思路:
    自己在那裡亂搞遞推公式,狀壓dp的思想很不錯,博博講的很精闢。我們算成n行的磚,每行有四。然後用4個01位表示一行,如果是0表示這一行不會佔用下一行的地方,如果是1表示會佔用下一行的磚。這樣想想就比較容易了。狀態轉移有三種:
1,當前行當前位為1,那麼直接轉移到下一位。
2,當前行當前位為0,那麼可以表示下一行可以為1.
3,當前行當前位和下一位為00,那麼下一行也可以為00。
   詳見AC程式碼:



AC程式碼:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;

int dp[1005][16];

void dfs(int r,int c,int cur,int nex)
//分別表示當前行,當前列,當前狀態,可轉移的狀態
{
    if(c>3)
    {
        dp[r+1][nex]+=dp[r][cur];
        return;
    }
    if(!(cur&(1<<c)))
    {
        dfs(r,c+1,cur,nex|(1<<c));   //豎著放,用1
        if(c<=2&&!(cur&(1<<(c+1))))
            dfs(r,c+2,cur,nex);  //也可以橫著放,兩個0
    }
    else
        dfs(r,c+1,cur,nex);   //位置被上面的佔了
}

int main()
{
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    int i,j;
    for(i=0;i<22;i++)   //22已經爆int32了
        for(j=0;j<16;j++)
            if(dp[i][j])
                dfs(i,0,j,0);

    int tes,x;
    cin>>tes;

    for(i=1;i<=tes;i++)
    {
        cin>>x;
        cout<<i<<" "<<dp[x][0]<<endl;
    }
    return 0;
}



相關文章