1. 程式人生 > >第八屆藍橋杯C組B組(國賽)第二題 磁磚樣式

第八屆藍橋杯C組B組(國賽)第二題 磁磚樣式

algorithm 內容 else PE 進制數 提交 數字 是個 tex

小明家的一面裝飾墻原來是 3*10 的小方格。

現在手頭有一批剛好能蓋住2個小方格的長方形瓷磚。

瓷磚只有兩種顏色:黃色和橙色。

小明想知道,對於這麽簡陋的原料,可以貼出多少種不同的花樣來。

小明有個小小的強迫癥:忍受不了任何2*2的小格子是同一種顏色。

(瓷磚不能切割,不能重疊,也不能只鋪一部分。另外,只考慮組合圖案,請忽略瓷磚的拼縫)

顯然,對於 2*3 個小格子來說,口算都可以知道:一共10種貼法,如【p1.png所示】

技術分享圖片

但對於 3*10 的格子呢?肯定是個不小的數目,請你利用計算機的威力算出該數字。

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

答案:(47分)

代碼:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#define xx 3
#define yy 4
using namespace std;
int s[5][12],c;
map<int
,int> q;///每種擺放用01表示不同顏色,則可以組成不同的30位二進制數,標記每一種擺放是否重復(後面重復肯定是有的) int check(int x,int y)///判斷xy位置與周圍形成的任何四個格子是否沖突 { for(int i = x - 1;i <= x;i ++) { for(int j = y - 1;j <= y;j ++) { int d = (s[i][j] == s[i + 1][j + 1]) + (s[i][j] == s[i][j + 1]) + (s[i + 1][j] == s[i][j]);
if(d == 3)return 0; } } return 1; } int dele() { int d = 0; for(int i = 1;i <= xx;i ++) { for(int j = 1;j <= yy;j ++) { d = d * 2 + s[i][j]; } } if(q[d]) { cout<<d<<endl; return 0; } return q[d] = 1; } void dfs(int x,int y) { if(x == xx + 1) { if(dele())c ++; return; } if(s[x][y] == -1) { if(s[x + 1][y] == -1) { for(int k = 0;k < 2;k ++) { s[x][y] = s[x + 1][y] = k; if(check(x,y) && check(x + 1,y))dfs(x + y / yy,y % yy + 1); } s[x][y] = s[x + 1][y] = -1; } if(s[x][y + 1] == -1) { for(int k = 0;k < 2;k ++) { s[x][y] = s[x][y + 1] = k; if(check(x,y) && check(x,y + 1))dfs(x + y / yy,y % yy + 1); } s[x][y] = s[x][y + 1] = -1; } } else dfs(x + y / yy,y % yy + 1); } int main() { for(int i = 1;i <= xx;i ++) { for(int j = 1;j <= yy;j ++) { s[i][j] = -1; } } for(int i = 1;i <= yy;i ++) { s[xx + 1][i] = -2; s[0][i] = -2; } for(int i = 1;i <= xx;i ++) { s[i][yy + 1] = -2; s[i][0] = -2; } dfs(1,1); cout<<c; }

第八屆藍橋杯C組B組(國賽)第二題 磁磚樣式