標題:磁磚樣式
system.out 爲啥是“磁”磚?????? 藍橋水到這樣了麼??????
小明家的一面裝飾牆原來是 3*10 的小方格。
現在手頭有一批剛好能蓋住2個小方格的長方形瓷磚。
瓷磚只有兩種顏色:黃色和橙色。小明想知道,對於這麼簡陋的原料,可以貼出多少種不同的花樣來。
(瓷磚不能切割,不能重疊,也不能只鋪一部分。另外,只考慮組合圖案,請忽略瓷磚的拼縫)
顯然,對於 2*3 個小格子來說,口算都可以知道:一共10種貼法,如【p1.png所示】但對於 3*10 的格子呢?肯定是個不小的數目,請你利用計算機的威力算出該數字。
注意:你需要提交的是一個整數,不要填寫任何多餘的內容(比如:說明性文字)
小明有個小小的強迫症:忍受不了任何2*2的小格子是同一種顏色。
答案: 101466
解題思路
這題是道填空題,而且數據也不是特別多,所以不用關心時間的問題,肯定能在幾秒內出結果。(若果寫對了)
這個題看到第一眼就可以看出來是dfs搜索+去重,這題dfs的問題在:如何判斷已經鋪滿瓷磚了。
解決辦法:我們在鋪瓷磚的時候,假如裝飾牆有n*m個方格,我們現在位於( x, y) ,無論我們此時橫着鋪還是豎着鋪( 如果(x , y) 還能鋪),或者不鋪,如果我們下一步能走到(x,y+1)就一定要走到(x,y+1),如果不能就去(x+1,1)。即我們在鋪第x+1行的時候保證前x行已經鋪滿了。當我們走到n+1行的時候,裝飾牆也就鋪滿了。
位運算+map 判重(話說這叫hash???) 當然也可用set< set<int > > s,最後結果就是s.size()。
AC代碼
#include <iostream>
#include <map>
#include <cstring>
using namespace std;
int mp[4][11],n=3,m=10,tot;
map <int,int> check;
bool Judge()
{
for(int i=1;i<=n-1;i++) {
for(int j=1;j<=m-1;j++) {
if((mp[i][j]+mp[i][j+1]+mp[i+1][j]+mp[i+1][j+1])%4 == 0)
return false;
}
}
return true;
}
void dfs(int x,int y)
{
if(x == n+1) {
if(Judge()) {
int bit=1,sum=0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
sum += bit*mp[i][j];
bit = bit << 1;
}
}
if(!check[sum]) {
tot++;
check[sum]++;
}
}
return;
}
if(mp[x][y] == -1) {
if(y < m && mp[x][y+1] == -1) { //橫着
for(int i=0;i<2;i++) {
mp[x][y] = i;
mp[x][y+1] = i;
if(y+2 <= m)
dfs(x,y+2);
else
dfs(x+1,1);
mp[x][y] = -1;
mp[x][y+1] = -1;
}
}
if(x < n && mp[x+1][y] == -1) { //豎着
for(int i=0;i<2;i++) {
mp[x][y] = i;
mp[x+1][y] = i;
if(y+1 <= m)
dfs(x,y+1);
else
dfs(x+1,1);
mp[x][y] = -1;
mp[x+1][y] = -1;
}
}
}
else {
if(y < m)
dfs(x,y+1);
else
dfs(x+1,1);
}
}
int main()
{
memset(mp,-1,sizeof mp);
tot = 0;
dfs(1,1);
cout << tot << endl;
}