您的位置:首页 > 编程语言 > Java开发

杭电1728bfs逃离迷宫java实现

2018-03-26 11:10 435 查看
Problem Description

  给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?

Input

  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,

  第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符’.’表示该位置为空地,字符’*’表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。

Output

  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。

Sample Input

2

5 5

…**

.*.

…..

…..

*….

1 1 1 1 3

5 5

…**

.*.

…..

…..

*….

2 1 1 1 3

Sample Output

no

yes

首先论对宽搜的认识,学习数据结构之前,一直看不懂什么是宽搜,当时遇到搜索题很是苦恼,只会用回溯法进行深搜,还是利用到了函数运行的机制(类似递归),第一次真正明白宽搜的运行机制是二叉树的遍历,有一种用队列的遍历方式(二叉树链接)才明白宽搜的运行机制,面对这题,深搜超时,可能有的大神优化能过。但是首先想到的应该是宽搜,核心点是转弯的次数。

1:刚开始我打算用boolean数组标记走过的位置,用class新类time表示点的转弯次数,后来错了。想了一想错的原因,右下右转两次,如果下右右只有一次但是晚走而没法走,所以这种想法是错的。

2:用数组标记当前点的最小转弯,如果新点,入队。若果比这个点的转弯次小于等于,也可以入队。这样就能保证最终找到最终答案,但是还是不
4000
过,超时。至于原因:楼梯模型(要克服楼梯的走楼梯而不直走的问题)

3:最终处理方案:使用优先队列,(java的需要自己百度学习一下),因为漫天都是C类的代码,教程,我根本不知道那个是优先队列。必须用优先队列优化。后来请教了学长帮我解决。优先队列让小节点先 入队。

wa了28次,第29次终于过了。

代码如下:

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
/*
* bfs 标记节点,计入最小节点   优先队列优化
*/
public class 杭电1728bfs {
static int a[][]= {{-1,0},{0,1},{1,0},{0,-1}};//左 上  右 下
static boolean judgle=false;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();  //测试数据
for(int t1=0;t1<t;t1++)
{
int m=sc.nextInt();//行数  Y
int n=sc.nextInt();//列数 X
sc.nextLine();
char[] []b=new char[m]
;//粗存数据
boolean c[][]=new boolean[m]
;//是否可走(障碍物记录)
int e[][]=new int[m]
;//粗存砖头数
for(int i=0;i<m;i++)//输入
{
String a=sc.nextLine();
b[i]=a.toCharArray();
}
for(int i=0;i<m;i++)//判断
{
for(int j=0;j<n;j++)
{
if(b[i][j]=='.')
{c[i][j]=true;}
}
}
int k, x1, y1, x2, y2;//转弯数   xy
k=sc.nextInt();x1=sc.nextInt();y1=sc.nextInt();x2=sc.nextInt();y2=sc.nextInt();
bfs(e,c,x1-1,y1-1,x2-1,y2-1,m,n,k);
if(judgle)
{System.out.println("yes");judgle=false;}
else
{System.out.println("no");}
}
}
private static void bfs(int e[][],boolean[][] c,int x, int y, int x2, int y2,int m,int n,int k) {
Queue<zuobiao> q1=new PriorityQueue<>(timecomepare);
e[y][x]=-1;
q1.add(new zuobiao(x,y));
while(!q1.isEmpty())
{
zuobiao exa=q1.peek();//头坐标
q1.poll();
int x1=exa.x;int y1=exa.y;
if(x1==x2&&y1==y2){if(exa.time<=k) {judgle=true;break;}}
else
for(int i=0;i<4;i++)
{
if(x1+a[i][0]<0||x1+a[i][0]>n-1||y1+a[i][1]<0||y1+a[i][1]>m-1||c[y1+a[i][1]][x1+a[i][0]]==false){}//不能走或者走过
else
{
zuobiao zuo=new zuobiao(x1+a[i][0],y1+a[i][1],exa.time,exa.fangxiang);
zuo.fangxiang=i;
if(zuo.fangxiang!=exa.fangxiang) {zuo.time++;}
if(e[y1+a[i][1]][x1+a[i][0]]>=zuo.time)//转头次数小于等于,入队
{q1.add(zuo);e[y1+a[i][1]][x1+a[i][0]]=zuo.time;}
else if(e[y1+a[i][1]][x1+a[i][0]]==0){//初始的没用过,入队
q1.add(zuo);
e[y1+a[i][1]][x1+a[i][0]]=zuo.time;
}
}
}

}
}
public static Comparator<zuobiao> timecomepare =new Comparator<zuobiao>()//实现comparator接口
{
public int compare(zuobiao a1,zuobiao a2)
{
return (int)(a1.time-a2.time);
}
};
}
class  zuobiao
{
int x;
int y;
int time;
int fangxiang;
public zuobiao(int x,int y)
{
this.x=x;
this.y=y;
this.fangxiang=-1;
this.time=-1;
}
public zuobiao(int x,int y,int time,int fangxiang)
{
this.x=x;
this.y=y;
this.time=time;
this.fangxiang=fangxiang;
}
}


不知道有什么不妥或者不对的地方。请大神更正
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: