第八屆藍橋杯決賽 磁磚樣式


標題:磁磚樣式

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

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

樣例


 

思路

  去年比賽時被這題坑了,一直想用輪廓線動態規划去做。。。其實直接暴力搜索就可以。

  依次枚舉每一個格子,每擺放滿一行,再嘗試去擺放下一行。在位置$(x,y)$處有兩種擺放方式:橫向和縱向。

  當擺滿所有格子的時候就檢查是否出現某個2*2的小格子是同一種顏色,以及這種擺放方式是否已經計算過。我是采用二進制來表示每一種能鋪滿的情況,黃色用0表示,橙色用1表示,再用map來記錄和判斷是否重復計算。

 


 

詳細代碼

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <map>
 4 #include <algorithm>
 5 using namespace std;
 6 const int w = 3, h = 10;
 7 int graph[w][h];
 8 int ans = 0;
 9 
10 map<int, int> Hash;
11 
12 //檢查2x2格子顏色是否相同
13 bool check_color() {
14     for(int i = 0; i < w; i++) 
15     for(int j = 0; j < h; j++) {
16         if(i+1 < w && j+1 < h) {
17             if((graph[i][j]+graph[i][j+1]+graph[i+1][j]+graph[i+1][j+1]) % 4 == 0) 
18                 return false;
19         }
20     }
21     return true;
22 }
23 
24 void fill_with_tile(int x, int y) {
25     if(graph[x][y] == -1) {
26         //橫向擺放
27         if(y+1 < h && graph[x][y+1] == -1) {
28 
29             for(int i = 0; i < 2; i++) {
30                 graph[x][y] = graph[x][y+1] = i;
31                 if(y == h-1) {  //鋪下一行
32                     fill_with_tile(x+1, 0);
33                 } else {        //鋪當前行的下一個格子
34                     fill_with_tile(x, y+1);
35                 }
36                 graph[x][y] = graph[x][y+1] = -1;
37             }
38 
39         }
40         //縱向擺放
41         if(x+1 < w && graph[x+1][y] == -1) {
42             for(int i = 0; i < 2; i++) {
43                 graph[x][y] = graph[x+1][y] = i;
44                 if(y == h-1) {  //鋪下一行
45                     fill_with_tile(x+1, 0);
46                 } else {        //鋪當前行的下一個格子
47                     fill_with_tile(x, y+1);
48                 }
49                 graph[x][y] = graph[x+1][y] = -1;
50             }
51         }
52     } else {
53         if(x == w-1 && y == h-1) { //成功鋪滿
54             if(check_color()) {
55                 //判斷是否出現重復情況
56                 int ret = 0, bit = 1;
57                 for(int i = 0; i < w; i++)
58                 for(int j = 0; j < h; j++) {
59                     ret += graph[i][j] * bit;
60                     bit *= 2;
61                 }
62                 if(!Hash.count(ret)) {
63                     Hash[ret] = 1;
64                     ans++;
65                 }
66             }
67             return;
68         }
69         if(y == h-1) {          //鋪下一行
70             fill_with_tile(x+1, 0);
71         } else {                //鋪當前行的下一個格子
72             fill_with_tile(x, y+1);
73         }
74     }
75 }
76 
77 int main() {
78     memset(graph, -1, sizeof(graph));
79     fill_with_tile(0, 0);
80     printf("%d\n", ans);
81     return 0;
82 }

 

只需要1s就算出來答案了,合理的鋪放方式共有101466種。

 


如有不當之處歡迎指出!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM