2017.瓷砖样式.dfs

  • 我也没想到怎么做,看别人题解看懂了
  • dfs()枚举所有的点,我看长方形瓷砖是2格的就莫名不知道该怎么枚举
  • 要求用2种颜色瓷砖铺满3*10的格子,且瓷砖能横着铺 竖着铺,
  • 遍历所有的点,dfs去铺,判断每个点是否铺过,标记第一个颜色为0,第二个颜色为1
  • 判断每个点铺了瓷砖没,没铺就铺瓷砖,铺了之后就判断该行是否铺完,否则换行或者接着下一个点继续铺,
  • 没有铺,判断是否到了最有一个点,没有就,判断接下来该往哪里铺
  • 每一种图的铺法用map<int,int>记录,写个hash函数映射存到map中,
  • 这里map.count()等价于map.find() == map.end(),判断存了没有
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <string.h>
#include <map>
#include <algorithm>

using namespace std;

const int w = 3,h = 10;
int e[w][h];
int ans;

map<int,int> Hash;

bool check() { //检查 2x2 的格子中是否颜色相同
for (int i=0; i<w; i++)
for (int j=0; j<h; j++)
if (i+1 < w && j+1 < h) //判断是否在图中 1+1+1+1 0+0+0+0
if ( (e[i][j] + e[i+1][j] + e[i][j+1] + e[i+1][j+1]) % 4 == 0 )
return false;
return true;
}
void fill(int x,int y) {
if (e[x][y] == -1) { //该点没有被填充过
// 每点枚举2种摆法,且有2中 颜色
if (y+1 < h && e[x][y+1] == -1) { // 判断边界+下一个点是否能摆放

for (int i=0; i<2; i++) { // 两种颜色
e[x][y] = e[x][y+1] = i;//横着摆 的 第一种颜色
if (y == h-1) //当前行已经满了,换行
fill(x+1,0);
else // 继续填下一个格子
fill(x,y+1);
//回溯
e[x][y] = e[x][y+1] = -1;
}
}
// 纵向摆放
if (x+1 < w && e[x+1][y] == -1) {

for (int i=0; i<2; i++) {
e[x][y] = e[x+1][y] = i;
if (y == h-1)
fill(x+1,0);
else
fill(x,y+1);
e[x][y] = e[x+1][y] = -1;
}
}
}
else { //如果该点被填充了
if (x == w-1 && y == h-1) {//判断dfs边界 ,是否所有的点都被填充完了
if ( check() ) { // 检查是否有 2x2 格子颜色是一样的
int res = 0;
int bit = 1;
for (int i=0; i<w; i++)
for (int j=0; j<h; j++) {
res += e[i][j] * bit;
bit *= 2;
}
if ( !Hash.count(res) ) { //判断res出现过没有,Hash是用来记录出现过的结果的
Hash[res] = 1;
ans++;
}
}
//都走完了 退出
return ;
}
if (y == h-1)
fill(x+1,0);
else
fill(x,y+1);
}
return ;
}
int main() {
memset( e, -1, sizeof e);
fill(0,0);
cout << ans;
return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!