/
1019_Separate the Animals (35).cpp
95 lines (90 loc) · 2.85 KB
/
1019_Separate the Animals (35).cpp
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <bits/stdc++.h>
using namespace std;
/*
算法思路:搜索+剪枝
1. 搜索所有可能情况,记录访问过的状态,避免重复搜索(矩阵压缩成二进制位,使用int64表示)
2. 对于找到的可能解,使用floodfill(BFS)进行animal和hole的数量统计,判断当前解是否合法
tips:
1. 原来的写法使用vector<int> path,来记录当前搜索路径,4,6两组用例答案错误,麻蛋的,不知道什么问题
2. 现在的版本全部改成二进制状态来表示
*/
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
int n, m, k, h;
string row;
bool vis[36];
char grid[6][6];
typedef long long int64;
unordered_set<int64> status;
int64 ans = 0LL;
bool check(int64 node) {
int holeNum = 0;
memset(vis, false, sizeof(vis));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int p = i*m+j;
if (grid[i][j] == 'w' || vis[p] || (node>>p)&1LL) continue;
bool isHole = true;
int animalNum = 0;
queue<int> q;
q.push(p);
vis[p] = true;
while (!q.empty()) {
p = q.front(); q.pop();
int cx = p/m, cy = p%m;
if (cx == 0 || cx == n-1 || cy == 0 || cy == m-1) isHole = false;
if (grid[cx][cy] == 'O' && ++animalNum > 1) return false;
for (int i = 0; i < 4; i++) {
int x = cx + dx[i], y = cy + dy[i];
if (x >= 0 && y >= 0 && x < n && y < m && grid[x][y] != 'w' && !vis[x*m+y] && !(node>>(x*m+y)&1LL)) {
q.push(x*m+y);
vis[x*m+y] = true;
}
}
}
if (isHole && ++holeNum > h) return false;
}
}
return holeNum == h;
}
void search(int64 node, int num) {
if (status.count(node)) return;
status.insert(node);
if (num == 0) {
if (check(node)) ans++;
return;
}
int64 cur = node;
int cnt = 0, x, y, cx, cy;
while (cur) {
if (cur & 1LL) {
x = cnt / m;
y = cnt % m;
for (int i = 0; i < 4; i++) {
cx = x + dx[i];
cy = y + dy[i];
if (cx >= 0 && cy >= 0 && cx < n && cy < m && \
grid[cx][cy] == '.' && !((node>>(cx*m+cy))&1LL)) {
search(node | (1LL<<(cx*m+cy)), num-1);
}
}
}
cnt++;
cur >>= 1LL;
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> k >> h;
for (int i = 0; i < n; i++) {
cin >> row;
for (int j = 0; j < row.size(); j++) grid[i][j] = row[j];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == '.') search(1LL<<(i*m+j), k-1);
}
}
cout << ans << endl;
return 0;
}