解救小Q
时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte
描述
小Q被邪恶的大魔王困在了迷宫里,love8909决定去解救她。迷宫里面有一些陷阱,一旦走到陷阱里,就会被困身亡:(,迷宫里还有一些古老的传送阵,一旦走到传送阵上,会强制被传送到传送阵的另一头。
现在请你帮助love8909算一算,他至少需要走多少步才能解救到小Q? (上下左右四个方向走,传送门可以多次使用)
输入
第一行为一个整数T,表示测试数据组数。每组测试数据第一行为两个整数N,M,(1 <= N, M <= 50)表示迷宫的长和宽。接下来有N行,每行M个字符,是迷宫的具体描述。
'.'表示安全的位置,'#'表示陷阱,
'Q'表示小Q的位置,'L'表示love8909所在位置,
数据保证love8909只有一个,数据也保证小Q只有一个。小写字母'a'-'z'表示分别表示不同的传送阵,数据保证传送阵两两配对。
输出
每组数据输出一行,解救小Q所需的最少步数,如果无论如何都无法救小Q,输出-1。
样例输入
2
5 5
....L
.###.
b#b#a
##.##
...Qa
5 5
....L
.###.
.#.#.
##.##
...Q.
样例输出
3
-1
一道挺容易想到思路,但是做起来有点复杂的题,好题。
AC代码:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> #include<queue> using namespace std; #define T 100 struct node { int x,y,cnt; node(){} node(int _x,int _y,int _cnt):x(_x),y(_y),cnt(_cnt){} }; node go[30][2];//传送门 char str[T][T]; bool vis[T][T]; int n,m; int fx[][2] = {{1,0},{0,1},{-1,0},{0,-1}}; int bfs(int x,int y) { memset(vis,false,sizeof(vis)); queue<node> q; q.push(node(x,y,0)); node p; while(!q.empty()) { p = q.front();q.pop(); for(int i=0;i<4;++i){ int tx = p.x+fx[i][0],ty = p.y+fx[i][1]; if(tx>=0&&tx<n&&ty>=0&&ty<m&&str[tx][ty]!='#'&&!vis[tx][ty]){ vis[tx][ty]=true; if(str[tx][ty]=='Q')return p.cnt+1; if(str[tx][ty]>='a'&&str[tx][ty]<='z'){//判断是否进入传送门 int d = str[tx][ty]-'a'; for(int j=0;j<2;++j){ if(tx!=go[d][j].x ||ty!=go[d][j].y){ tx=go[d][j].x; ty=go[d][j].y; break; } } } q.push(node(tx,ty,p.cnt+1)); } } } return -1; } int main() { #ifdef zsc freopen("input.txt","r",stdin); #endif int N,i,j,x,y; scanf("%d",&N); while(N--) { memset(go,-1,sizeof(go)); scanf("%d%d",&n,&m); for(i=0;i<n;++i){ for(j=0;j<m;++j){ scanf("\n%c",&str[i][j]); if(str[i][j]=='L')x=i,y=j; if(str[i][j]>='a'&&str[i][j]<='z'){ if(go[str[i][j]-'a'][0].x==-1){ go[str[i][j]-'a'][0].x=i; go[str[i][j]-'a'][0].y=j; } else { go[str[i][j]-'a'][1].x=i; go[str[i][j]-'a'][1].y=j; } } } } printf("%d\n",bfs(x,y)); } return 0; }