Loading

牛客小白月赛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
posted @ 2021-07-16 22:42  脂环  阅读(221)  评论(0编辑  收藏  举报