CDOJ 1002 解救小Q

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ROW_MAX_SIZE 50 
#define COL_MAX_SIZE 50

#define QUEUE_MAX_SIZE ROW_MAX_SIZE*COL_MAX_SIZE

char maze[ROW_MAX_SIZE][COL_MAX_SIZE]; //迷宫数组
int cost[ROW_MAX_SIZE][COL_MAX_SIZE]; //走到某个格子需要的最少步数
int flag[ROW_MAX_SIZE][COL_MAX_SIZE]; //标记迷宫格是否被访问过

struct letter_node{
	int x;
	int y;
}trans_gate[26][2];//传送门,保存26个字母的对应位置

struct char_node{
	int x;
	int y;
}qmaze[QUEUE_MAX_SIZE];//BFS队列

int front=0,rear=0;

int nextx[]={-1,0,1,0};//每个节点的子节点是其上下左右四个方向的格子,从上开始,逆时针计算
int nexty[]={0,-1,0,1};

int main(int argc,char *argv[])
{
	int n;
	scanf("%d",&n);//the number of cases
	while(n--){
		int N,M;
		scanf("%d%d",&N,&M);//the number of cols or rows
		getchar();//give up "\n"
		memset(trans_gate,-1,sizeof(trans_gate));//清空传送阵
		front=rear=0;
		int i,j;
		for(i=0;i<N;i++){//初始化迷宫和传送阵
			for(j=0;j<M;j++){
				scanf("%c",&maze[i][j]);
				cost[i][j]=0;
				flag[i][j]=0;
				if(maze[i][j]=='L'){//记录开始位置
					maze[i][j]='#';
					qmaze[rear].x=i;
					qmaze[rear].y=j;
					rear++;
					flag[i][j]=1;
				}
				if(maze[i][j]>='a' && maze[i][j]<='z'){//初始化传送阵
					if(trans_gate[maze[i][j]-'a'][0].x==-1){
						trans_gate[maze[i][j]-'a'][0].x=i;
						trans_gate[maze[i][j]-'a'][0].y=j;
					}else{
						trans_gate[maze[i][j]-'a'][1].x=i;
						trans_gate[maze[i][j]-'a'][1].y=j;
					}
				}
			}
			getchar();//丢弃每一行的换行符
		}
		int mark=0;
		while(front<rear){//BFS
			for(i=0;i<4;i++){
				int nx=qmaze[front].x+nextx[i];
				int ny=qmaze[front].y+nexty[i];//找到下一层节点
				if(nx<0 || ny <0 || nx >=N || ny >=M || flag[nx][ny] || maze[nx][ny]=='#')
					continue;//超出迷宫范围,或者已经访问过,或者是陷阱
				flag[nx][ny]=1;//标记已访问过
				int xtmp=nx,ytmp=ny;
				if(maze[nx][ny]>='a' && maze[nx][ny]<='z'){//遇到传送阵,传至另一端
					if(trans_gate[maze[nx][ny]-'a'][0].x==nx && trans_gate[maze[nx][ny]-'a'][0].y==ny){
						xtmp=trans_gate[maze[nx][ny]-'a'][1].x;
						ytmp=trans_gate[maze[nx][ny]-'a'][1].y;
					}else{
						xtmp=trans_gate[maze[nx][ny]-'a'][0].x;
						ytmp=trans_gate[maze[nx][ny]-'a'][0].y;
					}
				}
				nx=xtmp;
				ny=ytmp;
				cost[nx][ny]=cost[qmaze[front].x][qmaze[front].y]+1;//记录当前步骤数
				qmaze[rear].x=nx;
				qmaze[rear].y=ny;
				rear++;
				if(maze[nx][ny]=='Q'){
					printf("%d\n",cost[nx][ny]);
					mark=1;
				}
			}
			front++;
		}
		if(mark==0){
			printf("%d\n",-1);
		}
	}
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值