1. 程式人生 > >藍橋杯-磁磚樣式 | dfs+hash

藍橋杯-磁磚樣式 | dfs+hash

標題:磁磚樣式

小明家的一面裝飾牆原來是 3*10 的小方格。
現在手頭有一批剛好能蓋住2個小方格的長方形瓷磚。
瓷磚只有兩種顏色:黃色和橙色。
小明想知道,對於這麼簡陋的原料,可以貼出多少種不同的花樣來。
小明有個小小的強迫症:忍受不了任何2*2的小格子是同一種顏色。
(瓷磚不能切割,不能重疊,也不能只鋪一部分。另外,只考慮組合圖案,請忽略瓷磚的拼縫)
顯然,對於 2*3 個小格子來說,口算都可以知道:一共10種貼法,如【p1.png所示】
但對於 3*10 的格子呢?肯定是個不小的數目,請你利用計算機的威力算出該數字。

注意:你需要提交的是一個整數,不要填寫任何多餘的內容(比如:說明性文字)


思路:

看到是3*10的格子,可以考慮用dfs搜尋一遍。每個格子有兩種擺法,一種是橫著放,一種是豎著放,兩種顏色可以考慮用0,1表示,這樣最後判斷是否有重複的時候可以用位運算+Hash來判斷。

擺放瓷磚一定要遵循一行拜訪完再擺放下一行的規則,這樣可以避免少考慮情況。

程式碼:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <time.h>

using namespace std;

const int maxn=1005;
int mp[maxn][maxn];
int row,col,ans;

map<int,int> Hash;

bool check()
{
    for(int i=0;i<row;++i)
        for(int j=0;j<col;++j)
    {
        if(i+1<row&&j+1<col)
            if((mp[i][j]+mp[i+1][j]+mp[i][j+1]+mp[i+1][j+1])%4==0) return false;
    }
    return true;
}

void work(int x,int y)
{
    if(mp[x][y]==-1)
    {
        ///橫放
        if(y+1<col&&mp[x][y+1]==-1)
        {
            for(int i=0;i<2;++i)
            {
                mp[x][y]=mp[x][y+1]=i;
                if(y+1<col) work(x,y+1);
                else work(x+1,0);
                mp[x][y]=mp[x][y+1]=-1;
            }
        }
        ///縱向
        if(x+1<row&&mp[x+1][y]==-1)
        {
            for(int i=0;i<2;++i)
            {
                mp[x][y]=mp[x+1][y]=i;
                if(y+1<col) work(x,y+1);
                else work(x+1,0);
                mp[x][y]=mp[x+1][y]=-1;
            }
        }
    }
    else
    {
        if(x==row-1&&y==col-1)
        {
            if(check())
            {
                int sum=0,bit=1;
                for(int i=0;i<row;++i)
                    for(int j=0;j<col;++j)
                {
                    sum+=bit*mp[i][j];
                    bit<<=1;
                }
                if(!Hash[sum])
                {
                    ans++;
                    Hash[sum]++;
                }
            }
            return;
        }
        if(y==col-1) work(x+1,0);
        else work(x,y+1);
    }
}

int main()
{
    clock_t starttime,endtime;
    while(scanf("%d%d",&row,&col)!=EOF)
    {
        //starttime=clock();
        memset(mp,-1,sizeof(mp));
        ans=0;
        work(0,0);
        //endtime=clock();
        printf("%d\n",ans);
        //printf("--%.5f\n",double(endtime-starttime)/CLOCKS_PER_SEC);
        //time=4.20300s
    }

    return 0;
}