牛客小白月赛36 I. 四面楚歌(DFS)
链接:https://ac.nowcoder.com/acm/contest/11213/I
来源:牛客网
题目描述
在游戏中,因为一次错误的决断,你的士兵被敌方实行围剿。为了挽回人员损失,你不得不开启金手指暂停敌方士兵的移动,从而尽量让自己的士兵能成功突围。
已知地图是一块n×mn×m的区域,每块格子有以下几种类型:
.:表示此处为一块空地。
1:表示此处有敌方士兵,不许通过。因为开启了金手指,所以敌方士兵不会移动。
0:表示此处有我方士兵。
现规定我方士兵只能进行上/下/左/右四个方向的移动,只要某个士兵移动出了地图边界,那么就算该士兵突围成功。请问能有多少士兵成功突围。
输入描述:
第一行两个正整数nn,mm,n≤1000n≤1000,m≤1000m≤1000。接下来nn行,每行mm个字符,表示地图情况。
输出描述:
输出成功突围的士兵个数。
示例1
输入
复制
4 5
111..
101..
111..
..0..
输出
复制
1
直接枚举己方士兵不太容易,不妨换个角度,看看从边界开始dfs能遇到几个士兵,遇到士兵就将答案++同时把士兵变为空地。注意特判士兵在边界的情况。
#include <bits/stdc++.h>
using namespace std;
char mp[1005][1005];
int n, m;
int ans = 0;
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
bool vis[1005][1005];
void dfs(int x, int y) {
vis[x][y] = 1;
if(mp[x][y] == '0') {
ans++;
mp[x][y] = '.';
}
for(int i = 0; i < 4; i++) {
int nx = x + dir[i][0], ny = y + dir[i][1];
if(nx < 1 || nx > n || ny < 1 || ny > m || vis[nx][ny] || mp[nx][ny] == '1') continue;
dfs(nx, ny);
}
}
int main() {
cin >> n >> m;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++) {
scanf("%s", mp[i] + 1);
}
//边界的士兵
for(int i = 1; i <= m; i++) {
if(mp[1][i] == '0') {
ans++;
mp[1][i] = '.';
}
}
for(int i = 1; i <= m; i++) {
if(mp[n][i] == '0') {
ans++;
mp[n][i] = '.';
}
}
for(int j = 2; j <= n - 1; j++) {
if(mp[j][1] == '0') {
ans++;
mp[j][1] = '.';
}
}
for(int j = 2; j <= n - 1; j++) {
if(mp[j][m] == '0') {
ans++;
mp[j][m] = '.';
}
}
//dfs
for(int i = 1; i <= m; i++) {
if(mp[1][i] == '.') {
dfs(1, i);
}
}
for(int i = 1; i <= m; i++) {
if(mp[n][i] == '.') {
dfs(n, i);
}
}
for(int j = 2; j <= n - 1; j++) {
if(mp[j][1] == '.') {
dfs(j, 1);
}
}
for(int j = 2; j <= n - 1; j++) {
if(mp[j][m] == '.') {
dfs(j, m);
}
}
cout << ans;
return 0;
}
//000
//000
//000