RQNOJ - PID83 魔兽世界 (BFS)

题目描述

小A在WOW中是个小术士.作为一名术士,不会单刷副本是相当丢脸的.所谓单刷副本就是单挑BOSS了,这么有荣誉感的事小A怎么会不做呢?于是小A来到了厄运之槌开始了单刷.小A看了看,厄运之槌的地图是一个N*M的矩形(N,M<=100),上面遍布了小怪和传送门.例如(1表示有小怪,0表示无小怪,大写字母表示传送门,传送门:例如,走到 B 传送门点将传送到另一个 B 传送点(次数无限,但每次进入传送点只传送过去,不会在传送回来)数据保证每个传送门有且仅有相对应的另一个传送门):

而入口在左上方(1,1),BOSS却躲在右下方(N,M).小A非常急切的想要完成单刷然后去向其他那些战士啊盗贼啊不会单刷的职业炫耀炫耀,所以呢,小A绝不会在小怪身上浪费时间(当然是绕开他们),并且想通过传送门尽快到达BOSS身边.看啊看,想啊想,还是没找出最快的路.终于,灵机一动,想什么啊,编程呗!

路线如图:

[数据规模]

对60%的数据,n,m<=20

对100%的数据,n,m<=100

输入格式

第一行2个数据:n m;

下面n行,每行m个数(入口点和BOSS点无怪和传送门),表示厄运之槌的地图。地图数据之间无空格。每步只能走一格,方向上下左右。左上角为入口点,右下角为出口点.

输出格式

一个整数,表示小A最少需要走多少步。如果小A不能走到目标,则输出No Solution.

题目地址:点击打开链接


——————————————————————————————————————————————————


WA了几次,通过对比AC的源码,发现了以下问题:

 M*i + j;
1、传送门坐标处理:如果map是从1到N存放的话,坐标应该 x*(m+1) + y存放,而不是 x*m + y

2、应通过传送门传送后,产生传送后的点再判断是否vis过,另:如果两者都一起写入vis的话也会出错。

3、数据读入出错,不知什么原因,一个一个的getchar提交上去错了8个点,用scanf整行的话却可以AC


#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
struct P
{
	int x,y;
	P(int a, int b): x(a), y(b){};
};

//4个移动方向
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
char map[110][110];
int N, M;
int cs[30][3];
//距离起点的距离
int d[110][110];
int bfs(P sp, P gp)
{
	//bfs队列
	queue<P> que;
	//将起点加入队列
	que.push(sp);
	//初始化距离数据,设为无穷远,-1为边界(暂无用)
	memset(d, 0x3f, sizeof(d));
	d[sp.x][sp.y] = 0;
	while(que.size())
	{
		//出队
		P p = que.front();	que.pop();
		//找到终点
		if(p.x == gp.x && p.y == gp.y)
			break;

		//4个方向
		for(int i = 0; i < 4; i++)
		{
			int nx = p.x + dx[i], ny = p.y + dy[i];
			//距离为无穷远表示尚未走过
			if(0<=nx&&nx<N && 0<=ny&&ny<M/* && d[nx][ny] == INF */&& map[nx][ny]!='1')
			{
				//d[nx][ny] = d[p.x][p.y] + 1;
				if('A'<=map[nx][ny]&&map[nx][ny]<='Z')
				{
					int t = map[nx][ny] - 'A';
					if(cs[t][0] == M*nx + ny)
					{
						nx = cs[t][1] / M;
						ny = cs[t][1] % M;
					}
					else
					{
						nx = cs[t][0] / M;
						ny = cs[t][0] % M;
					}
				}
				if( d[nx][ny] != INF )
					continue;
				que.push(P(nx, ny));
				d[nx][ny] = d[p.x][p.y] + 1;
			}
		}
	}
	return d[gp.x][gp.y];
}

int main()
{
	/*while*/(scanf("%d%d", &N, &M));
	{
		for(int i = 0; i < N; i++)
		{
			scanf("%s",&map[i][0]);
			for(int j = 0; j < M; j++)
			{
				if('A'<=map[i][j]&&map[i][j]<='Z')
				{
					int t = map[i][j]-'A';
					cs[t][cs[t][2]++] = M*i + j;
				}
			}
		}

		int ans =  bfs(P(0, 0), P(N-1, M-1));
		if(ans!=INF)
			printf("%d\n", ans);
		else
		{
			printf("No Solution.\n");
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值