题目:小明家的一面装饰墙原来是 3*10 的小方格。现在手头有一批刚好能盖住2个小方格的长方形瓷砖。瓷砖只有两种颜色:黄色和橙色。小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。小明有个小小的强迫症:忍受不了任何2*2的小格子是同一种颜色。(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)显然,对于 2*3 个小格子来说,口算都可以知道:一共10种贴法。
但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。
dfs:确定返回条件有哪些。
依条件深度遍历。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<stack> 7 #include<set> 8 #include<map> 9 #include<vector> 10 #include<cmath> 11 const int maxn = 1e5 + 5; 12 typedef long long ll; 13 using namespace std; 14 int ans = 0; 15 int vis[25][25]; 16 int n, m; 17 //map<string,int> s; 18 set<string> s; 19 void dfs(int count) { 20 for (int i = 1; i < n; i++) {//出现四个小方格是同一种颜色 21 for (int j = 1; j < m; j++) { 22 if (vis[i][j] && vis[i][j] == vis[i + 1][j] && vis[i][j] == vis[i][j + 1] && vis[i][j] == vis[i + 1][j + 1]) 23 return; 24 } 25 } 26 if (count == n * m) {//是一种涂法 27 string str = ""; 28 for (int i = 1; i <= n; i++) {// ToString 29 for (int j = 1; j <= m; j++) { 30 str += '0' + vis[i][j]; 31 } 32 } 33 s.insert(str); //set去重 34 } 35 if (count >= n * m) 36 return; 37 int x = 0, y = 0; 38 bool flag = 0; 39 for (int i = 1; i <= n; i++) {//找到还没有涂色的 40 for (int j = 1; j <= m; j++) { 41 if (!vis[i][j]) { 42 x = i; 43 y = j; 44 flag = 1; 45 break; 46 } 47 } 48 if (flag) 49 break; 50 } 51 //if (!flag) 52 // return; 53 if (y + 1 <= m && !vis[x][y + 1]) {//竖着涂 54 vis[x][y + 1] = 1; 55 vis[x][y] = 1; 56 dfs(count + 2); 57 vis[x][y + 1] = 2; 58 vis[x][y] = 2; 59 dfs(count + 2); 60 vis[x][y + 1] = 0; 61 vis[x][y] = 0; 62 } 63 if (x + 1 <= n && !vis[x + 1][y]) {//横着涂 64 vis[x][y] = 1; 65 vis[x + 1][y] = 1; 66 dfs(count + 2); 67 vis[x][y] = 2; 68 vis[x + 1][y] = 2; 69 dfs(count + 2); 70 vis[x][y] = 0; 71 vis[x + 1][y] = 0; 72 } 73 } 74 75 int main() { 76 cin >> n >> m; 77 dfs(0); 78 ans = s.size(); 79 printf("%d ", ans); 80 return 0; 81 }
参考链接:https://blog.csdn.net/red_red_red/article/details/90108132