【2011.10.29模拟】迷宫题解

题目描述

北京地图可以看作是R*C的网格,奥运会期间对有的地方要进行交通管制,有的地方不允许进入,有的地方对离开时的行驶方向有限制:有的只允许走到上下两个相邻的格子,有的只允许走到左右两个相邻的格子,没有的任何限制的地方上下左右四个方向都允许。

现在给你地图的描述,格子的描述如下:
● “+”表示可以向任意方向(上、下、左、右)移动一格;
● “-”表示只能向左右方向移动一格;
● “|”表示只能向上下方向移动一格;
● “*”表示该位置不能到达。

你的任务是计算出从左上角到右下角的最少需要经过的格子数。

输入
输入第一行一个整数t(1<=t=10)表示有t组测试数据。
每一个测试数据,第一行一个整数r,第二行一个整数c(1<=r,c<=100)表示地图是r行c列的,接下来r行,每行c个字符,每个字符是{+,,-,|}中的一种。你可以假设左上角不会是“”。

输出
输出有t行,每行一个整数表示对应测试数据所需的最少格子数,如果到达不了右下角输出-1。

样例输入
3
2
2
-|
+
3
5
+||
+
+++|+
**–+
2
3
++
+
+

样例输出
3
7
-1

数据范围限制

提示
50% 1<=r,c<=20
100% 1<=r,c<=1000

难度:⭐⭐⭐

方法:记忆化搜索(BFS)

实际分数:90.9

方法1:DFS

这个就没什么好说的了
DFS直接暴力就行,预计分数40~80不等,不是满分的方法这里就先跳过辣

方法2:正解BFS

首先我们来分析一下这一题,
这一题每个点走的方法都不大一样,跟我们平时做的那些四向扩展的题不同,
所以步骤可能较繁琐,很多童鞋就是这样懵逼

在这里插入图片描述
步骤虽然繁琐,但是也很好做,只要学过 BFS这题也就还好吧…
四个不同的符号:

*直接跳过(这说法不准确,因为“*”就是障碍,压根去不了这点)
1上下走
-左右走
+怎么走都行

代码很长,但是为什么好做呢?
因为我们有秘密武器:ctrl+c
这题基本就完事儿了,你也许会问我:如此简单汝为何一开始会错?
我只能告诉你:我用错了memset…

在这里插入图片描述
不知为什么,我用的memset没用…

题外话:也许是我没用

在这里插入图片描述
走开走开…
好,疑问又来了:为什么汝改出来了还是90.9?
呵,呵呵
因为忘记特判了…

if(r==1&&c==1)//咋办?

printf("1");  //就是这错QAQ...

. . . . . . . . . . . . . . . . . . . . . . . . .酷 的. . . . . . . . . . . . . . . . . . . . . . . . .

//已加防抄袭辣
#include<iostream>
using namespace std;
int t,r,c,book[1005][1005],p[1000005][3];
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
char str[1005][1005];
int mian(){
	in(t);
	//读入
	for(int i=1;i<=t;i++){
		in(r,c);
		if(r==1&&c==1) ...
		int flag=0;
		for(int j=0;j<r;j++)
			cin>>str[j];
		int h=0,t=1;
		memset(book,0,sizeof(0));
		memset(p,0,sizeof(0));
		book[0][0]=1;
		p[1][0]=p[1][1]=0;
		p[1][2]=1;
		while (h<t){
			h++;
			//几种符号的遍历方法
			if(str[p[h][1]][p[h][0]]=='+'){
				for(int i=1;i<=4;i++){
					int xx=p[h][0]+dx[i];
					int yy=p[h][1]+dy[i];
					if(xx>=0&&xx<r&&yy>=0&&yy<c&&str[xx][yy]!='*'&&book[xx][yy]==0){
						t++;
						book[xx][yy]=1;
						p[t][0]=xx;
						p[t][1]=yy;
						p[t][2]=p[h][2]+1;
						if(xx==r-1&&yy==c-1){
							printf("%d\n",p[t][2]);
							flag=1;
							break;
						}
					}
				}
				if(flag==1) break;
			}
			if(str[p[h][1]][p[h][0]]=='|'){
				for(int i=1;i<=2;i++){
					int xx=p[h][0]+dx[i];
					int yy=p[h][1]+dy[i];
					if(xx>=0&&xx<r&&yy>=0&&yy<c&&str[xx][yy]!='*'&&book[xx][yy]==0){
						t++;
						book[xx][yy]=1;
						p[t][0]=xx;
						p[t][1]=yy;
						p[t][2]=p[h][2]+1;
						if(xx==r-1&&yy==c-1){
							printf("%d\n",p[t][2]);
							flag=1;
							break;
						}
					}
				}
				if(flag==1) break;
			}
			if(str[p[h][1]][p[h][0]]=='-'){
				for(int i=3;i<=4;i++){
					int xx=p[h][0]+dx[i];
					int yy=p[h][1]+dy[i];
					if(xx>=0&&xx<r&&yy>=0&&yy<c&&str[xx][yy]!='*'&&book[xx][yy]==0){
						t++;
						book[xx][yy]=1;
						p[t][0]=xx;
						p[t][1]=yy;
						p[t][2]=p[h][2]+1;
						if(xx==r-1&&yy==c-1){
							printf("%d\n",p[t][2]);
							flag=1;
							break;
						}
					}
				}
				if(flag==1) break;
			}
		}
		if(flag==0) printf("-1\n");
	}
	return 0;
}```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值