杭电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次终于过了。
代码如下:
不知道有什么不妥或者不对的地方。请大神更正
给定一个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; } }
不知道有什么不妥或者不对的地方。请大神更正
相关文章推荐
- 杭电1728逃离迷宫解法二 BFS 搜索
- 杭电1728 逃离迷宫(bfs过)
- 杭电 1728 逃离迷宫(BFS)
- 杭电1728逃离迷宫 BFS 搜索
- HDU 1728 逃离迷宫 BFS
- hdu 1728 逃离迷宫 bfs
- hdu 1728 逃离迷宫(bfs)
- bfs hdu 1728 逃离迷宫
- HDU 1728 逃离迷宫 BFS
- HDU 1728 逃离迷宫(BFS)
- HDU 1728逃离迷宫(DFS或者BFS)
- HDU 1728 逃离迷宫(拐弯问题,对BFS最优解的新理解)
- hdu 1728 逃离迷宫 bfs
- hdu 杭电 1728 逃离迷宫
- hdu 1728 逃离迷宫 (bfs)
- hdu 1728 逃离迷宫(BFS)
- hdu 1728 逃离迷宫(BFS 有 限制条件,陷阱比较多)
- hdu 1728 逃离迷宫(BFS)
- HDU 1728逃离迷宫(DFS或者BFS)
- hdu 1728 逃离迷宫 java BFS + 一搜到底