一、题目大意
有一个r*c的网格,网格中每一格都会有一个字符N,S,W,E(N是向上走1格,S是向下走1格,W是向左走1格,E是向右走1格)。有一个机器人将会在网格最上方进入网格(可以定义最上方的那一行为第1行),在指定了入口所在的列数bc之后,它就会从第1行第bc列进入网格,并且根据所到达网格中的字符确定下一步走的方向。机器人最终会遇到两种情况:
1.走出网格。
2.走进循环,也就是会在某几格循环移动。
现在输入r,c,bc,以及网格中的每一个字符,通过编程求出机器人最终会遇到哪种情况
二、思路
1.如果是第一种情况,用ans记录最终步数;如果是第二种情况,ans最终表示为只走一次的步数,再用ans2表示循环步数。
2.map数组记录网格中的每一个字符。
3.开始我只是把vis单纯地用来记录某一格是否已经访问过,但是后来考虑到题目的第二种情况后,觉得vis数组也可以用来记录首次到达某一格经历的步数。
4.map和vis两个数组在分析每一组数据前都要记得清零。
5.只要每一次移动后,所在的那一格(x,y)在网格内,并且没有被访问过,就说明符合题意,ans加1(此时的ans是用来记录累计步数的),并且把ans赋值给vis[x][y],然后根据那一格的字符决定下一步的移动方向。
6.移动后,如果x或y在网格范围之外,就表示走出网格了,输出累计步数即可。
7.移动后,如果发现(x,y)已经访问过,说明走进了循环,经过验算可以得到下面的代码中对ans2和ans的计算方式,然后按题目要求输出即可。
三、代码
#include<iostream>
#include<cstring>
using namespace std;
char map[15][15];
int vis[15][15];
int main()
{
int r,c,bc,x,y,ans,ans2;
while(cin >> r >> c >> bc, r||c||bc)
{
ans=0; ans2=0;
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
for(int i=1; i<=r; i++)
{
for(int j=1; j<=c; j++)
{
cin >> map[i][j];
}
}
x=1; y=bc;
while(x>=1 && x<=r && y>=1 && y<=c && !vis[x][y])
{
ans++;
vis[x][y] = ans;
switch(map[x][y])
{
case 'N': x--; break;
case 'S': x++; break;
case 'W': y--; break;
case 'E': y++; break;
}
}
if(x<1 || x>r || y<1 || y>c)
{
cout << ans << " step(s) to exit" << endl;
}
else if(vis[x][y])
{
ans2 = ans-vis[x][y]+1;
ans = vis[x][y]-1;
cout << ans << " step(s) before a loop of " << ans2 << " step(s)" << endl;
}
}
return 0;
}