Escape
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1234 Accepted Submission(s): 524
Problem Description
You find yourself trapped in a large rectangular room, made up of large square tiles; some are accessible, others are blocked by obstacles or walls. With a single step, you can move from one tile to another tile if it is horizontally or vertically adjacent (i.e. you cannot move diagonally).
To shake off any people following you, you do not want to move in a straight line. In fact, you want to take a turn at every opportunity, never moving in any single direction longer than strictly necessary. This means that if, for example, you enter a tile from the south, you will turn either left or right, leaving to the west or the east. Only if both directions are blocked, will you move on straight ahead. You never turn around and go back!
Given a map of the room and your starting location, figure out how long it will take you to escape (that is: reach the edge of the room).
Input
On the first line an integer t (1 <= t <= 100): the number of test cases. Then for each test case:
a line with two integers separated by a space, h and w (1 <= h, w <= 80), the height and width of the room;
then h lines, each containing w characters, describing the room. Each character is one of . (period; an accessible space), # (a blocked space) or @ (your starting location).
There will be exactly one @ character in each room description.
Output
For each test case:
A line with an integer: the minimal number of steps necessary to reach the edge of the room, or -1 if no escape is possible.
Sample Input
2 9 13 ############# #@..........# #####.#.#.#.# #...........# #.#.#.#.#.#.# #.#.......#.# #.#.#.#.#.#.# #...........# #####.####### 4 6 #.#### #.#.## #...@# ######
Sample Output
31 -1
Source
Recommend
lcy | We have carefully selected several similar problems for you: 2363 1175 1728 1495 2362
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
#define inf 99999999
#define maxn 100
/*
题意:在走的过程中能转弯就转弯不可以直走。。。
注意点:状态终止条件是边界而不是边界以外,
这是和我平时习惯不同的地方。
设置flag判断是否可以直走时,有个注意的地方就是
在两边判断已经走过的情情况下理所应当也要更新flag变量来标识。。
这题的状态权重和普通BFS一致,无需优先队列
*/
int n,m;
int sx,sy;
char c;
int vis[4][maxn][maxn];
int mp[maxn][maxn];
struct Node
{
int x,y,cnt;
int dir;
Node(int p=0,int q=0,int r=-1,int t=0)
{
dir=r;
x=p,y=q;
cnt=t;
}
};
int dir1[]={-1,0,1,0};
int dir2[]={0,-1,0,1};//
Node path[maxn][maxn];
bool judge(int x,int y)
{
if(x==0||x==n) return false;
if(y==0||y==m) return false;
return true;
}
int BFS()
{
memset(vis,0,sizeof(vis));
int tx,ty;
Node tmp;
queue<Node> seq;
seq.push(Node(sx,sy));
while(!seq.empty())
{
Node t=seq.front();
seq.pop();
if(!judge(t.x,t.y)) return t.cnt-1;
bool flag=false;
for(int i=0;i<4;i++)
{
if((i&1)!=(t.dir&1)||t.dir<0)
{
tx=t.x+dir1[i];
ty=t.y+dir2[i];
if(!judge(tx,ty)) return t.cnt+1;
if(mp[tx][ty]) continue;//有墙或已经走过
flag=true;
if(vis[i][tx][ty]) continue;
seq.push(Node(tx,ty,i,t.cnt+1));
vis[i][tx][ty]=1;
}
}
if(!flag)//无路可走
{
tx=t.x+dir1[t.dir];
ty=t.y+dir2[t.dir];
//if(tx<0||tx>=n||ty<0||ty>=m) continue;
if(!judge(tx,ty)) return t.cnt+1;
if(mp[tx][ty]==0&&vis[t.dir][tx][ty]==0)
{
seq.push(Node(tx,ty,t.dir,t.cnt+1));
vis[t.dir][tx][ty]=1;
}
}
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
int t; scanf("%d",&t);
getchar();
while(t--)
{
cin>>n>>m;
//scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>c;
// scanf("%c ",&c);
if(c=='#') mp[i][j]=1;
else mp[i][j]=0;
if (c=='@') {sx=i,sy=j;}
}
printf("%d\n",BFS());
}
return 0;
}