ICPC小米邀請賽 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;
}