藍橋杯-磁磚樣式 | dfs+hash
阿新 • • 發佈:2019-01-30
標題:磁磚樣式
小明家的一面裝飾牆原來是 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; }