2020ICPC·小米 网络选拔赛第一场 I.Walking Machine

题目:

Given a maze of size n×m, where upper left corner is (1,1)
and lower right corner is (n, m). For each cell (x, y) , there is exactly one character c (c∈{W,A,S,D}) on it, denoting the moving restriction:

  • If c=W , you can only go up from this cell, specifically go from (x, y)to (x-1, y)
  • If c=A , you can only go left from this cell, specifically go from(x,y) to (x,y−1)
  • If c=S, you can only go down from this cell, specifically go from(x,y) to (x+1,y)
  • If c=D , you can only go right from this cell, specifically go from (x,y) to (x,y+1)

    We say one is out if x < 1 or x > n or y < 1 or y > m holds, now you should determine the number of cells that one can be out if start walking on it.

输入描述:
The first line contains two integers n,m (1≤n,m≤1000), denoting the size of the maze.

Following n lines each contains a string of length m , where the j-th character in i-th line s(i, j) ( s (i,j)∈{W,A,S,D}) denotes the character on cell (i, j).
输出描述:
Only one line containing one integer, denoting the number of cells that can make one out.

输入
3 4
DDSD
AWAA
WASD

输出
6
说明
The 6 cells are (1, 4),(2, 1),(3, 1),(3, 2),(3, 3),(3, 4) respectively.

题意:判断一个迷宫中有几个点可以走出去,每个点会有一个方向,也就是我们键盘上的WASD(向上、向左、向下、向右)

题解:我首先是把最外围那圈能直接走出去的做一个标记(其实不用也行,可以直接搜),然后其他的点依次判断是否能走出去,重点就是几个剪枝,假如之前遍历过的点并且不能走出,那么这些所有的点下一次走到的时候肯定走不出去,如果之前遍历的点可以走出去,那么所有的点下次被走到时肯定肯定可以走出去。(bfs也可做)

代码:

#include<stdio.h> 
#include<iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;
const int N = 1005;
char map[1005][1005];
int can[N][N], vis[N][N]; //vis:标记之前是否走过, can:是否一定可以走出去或者走不出去 
int cnt = 0;
int flag = 0;
int n, m;
void dfs(int x, int y)
{
	if(can[x][y] == 1) //如果之前已经遍历过, 该点可以到达 
	{
		cnt++;
		flag = 1; //标记一下可以走出迷宫 
		return;
	}
	if(can[x][y] == -1) return; //该点不能走出去 
	if(vis[x][y])
	{
		can[x][y] = -1; //重复遍历, 一定无法走出去 
		return;
	}
	if(map[x][y] == 'W' )
	{
		vis[x][y] = 1;
		dfs(x - 1,y);
		vis[x][y] = 0;
		if(flag == 0) can[x][y] = -1; //如果最后无法到达, 将此次遍历过的所有点标为不可行 
		else can[x][y] = 1; //否则一定可以走出去(比赛的时候忘写了,直接T) 
	}
	else if(map[x][y] == 'S')
	{
		vis[x][y] = 1;
		dfs(x + 1,y);
		vis[x][y] = 0;
		if(flag == 0) can[x][y] = -1;
		else can[x][y] = 1;
	}
	else if(map[x][y] == 'A' )
	{
		vis[x][y] = 1;
		dfs(x,y - 1);
		vis[x][y] = 0;
		if(flag == 0) can[x][y] = -1;
		else can[x][y] = 1;
	}
	else if(map[x][y] == 'D')
	{
		vis[x][y] = 1;
		dfs(x,y + 1);
		vis[x][y] = 0;
		if(flag == 0) can[x][y] = -1;
		else can[x][y] = 1;
	}
}

int main()
{
	freopen("cin.in", "r", stdin);
	freopen("cout.out", "w", stdout);
	memset(can, 0, sizeof(can));
	memset(vis, 0, sizeof(vis));
	scanf("%d%d", &n, &m);
	getchar();
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			scanf("%c", &map[i][j]);
			if(i == 1 || j == 1 || i == n || j == m)
			{
				if(j == 1 && map[i][j] == 'A') can[i][j] = 1;
				if(i == 1 && map[i][j] == 'W') can[i][j] = 1;
				if(j == m && map[i][j] == 'D') can[i][j] = 1;
				if(i == n && map[i][j] == 'S') can[i][j] = 1;	
			}
			
		}
		getchar();
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			flag = 0;
			if(can[i][j] == 1) cnt++;
			else dfs(i, j);
		}
	}
	cout << cnt << endl;
	return 0;
}

posted @ 2020-10-25 20:03  ~K2MnO4  阅读(216)  评论(0)    收藏  举报