1091.二维矩阵中的最短路径
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1091.二维矩阵中的最短路径相关的知识,希望对你有一定的参考价值。
参考技术A 题目思路:使用dijkstra算法,因为题目的特殊性,没有必要严格按照dijkstra去执行,可以适当简化,比如我这里并没有设计bool数组去标记S集和U集,因为没必要。也没有用优先队列去装距离。
复习dijkstra算法:
算法目的:
求得 单个定点 到 其余各个点的最短距离
算法步骤:
1.设计S集、U集,S中放已经找到最短路径的点,U集放尚未处理的点
2.设计3个状态集合,dist和useddist存储当前已经找到的从单个定点到其余各个点的最小距离(算法没执行完的话,不一定是最小距离,执行完之后才是),used[i]存储是否已经处理完第i个节点,用来区分是S集还是U集。
3.每次从U集中取出从 单个定点 到U集中的点 路径最短的点,然后以该点为中间节点,更新一遍U集中 其它点的距离。(选U集中的最短路径可以借助优先队列优化算法,用一个最小堆,每次弹出最短距离的顶点,结合used来判断是否作处理)
求java实现矩阵图上任意两点的最短路径源码
基本要求
以矩阵表示地图,
1,1,1,1,1,1,1,1,1,1,1
1,0,1,0,1,0,0,0,0,0,1
1,0,1,0,0,0,1,0,1,1,1
1,0,0,0,1,0,1,0,0,0,1
1,0,1,1,0,0,1,0,0,1,1 0代表可以通过,1代表不可通过
1,0,1,0,1,1,0,1,0,0,1
1,0,0,0,0,0,0,0,1,0,1
1,0,1,0,1,0,1,0,1,0,1
1,0,0,1,0,0,1,0,1,0,1
1,1,1,1,1,1,1,1,1,1,1
可以任意设定起点和终点,可以任意设定地图,输出路径和步数。
比如我要找从右下角的那个1到矩阵第三行第4列的那个元素的最短路径,应该怎么做。我想要的是java源代码,最好能附上一些解释。想了好久,没想出来,拜托各位帮忙了
我用的是递归调用方法,有个小问题就是在打印步数的时候是返向的,原因是就是程序不断的调用自己,到最后判断基值位准退出调用。这才开始从栈里取出方法进行执行的原因。
代码欣赏:
public static int step = 1;
public static StringBuffer printStep = new StringBuffer();
public static int[][] maze =1,1,1,1,1,1,1,1,1,1,1,
1,0,1,0,1,0,0,0,0,0,1 ,
1,0,1,0,0,0,1,0,1,1,1 ,
1,0,0,0,1,0,1,0,0,0,1 ,
1,0,1,1,0,0,1,0,0,1,1 ,// 0代表可以通过,1代表不可通过
1,0,1,0,1,1,0,1,0,0,1 ,
1,0,0,0,0,0,0,0,1,0,1 ,
1,0,1,0,1,0,1,0,1,0,1 ,
1,0,0,1,0,0,1,0,1,0,1 ,
1,1,1,1,1,1,1,1,1,1,1 ;
public static void main(String[] args)
int i, j; //循环记数变量
Sample.way(1, 1);//二维数组起始值从下标1,1开始
System.out.println("起点从坐标 x = 1, y = 1开始");
System.out.println("终点坐标是 x = 8, y = 9结束");
System.out.println("这是迷宫图表");
System.out.println(" 0 1 2 3 4 5 6 7 8 9 10");
System.out.println(" +---+---+---+---+---+---+---+---+---+---+---+---+---+");
for(i = 0; i < 10; i++)
System.out.print(" " + i + "‖");
for(j = 0; j < 11; j++)
System.out.print("-" + maze[i][j] + "-‖");
System.out.println("");
System.out.println(" +---+---+---+---+---+---+---+---+---+---+---+---+---+");
//打印显示步数
System.out.print(printStep.toString());
public static boolean way(int x, int y)
if(maze[8][9] == 2)//代表递归终止条件(也就是当走出出口时标记为 2)
return true;
else
if(maze[y][x] == 0)
maze[y][x] = 2;
/*
* 下面if判断条件代表当前坐标为基点,
* 根据判断对当前位置进行递归调用:如:
* 往上、往右上、往右、往右下、往下、
* 往左下、往左、往左上的坐标是否可走,
* 判断是否可走的返回条件是:
* 2代表可通过、1代表不能通过、3表示已经走过,但是未能走通。
*/
if(way(x, y - 1))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else if(way(x + 1, y - 1))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else if(way(x + 1 , y))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else if(way(x + 1, y + 1))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else if(way(x, y + 1))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else if(way(x - 1, y + 1))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else if(way(x - 1, y))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else if(way(x - 1, y - 1))
printStep.append("第 " + step + " 步的所走的位置是 x = " + x + " y = " + y + "\\n");
step++;
return true;
else
maze[y][x] = 3;
return false;
else
return false;
复制代码前需要楼主自己创建个 类
Sample.way(1, 1);这句代码是我的类的静态调用,改下XXXXX.way(1, 1);
XXXXX代表你创建的类。
下面是这个程序运行后的截图
参考技术A 一楼正解离散数学中对这一个算法有详细解释。。
大概思路就是
如果设置点A 为起点,则找到所有与A相临的点
有几个点就几条路。。然后挨个往下找。
在与所有端点相临的所有点中,如果有发现B(终点)则这条路就是最近的
如果考虑每条路的长度不是相等的情况下,那就得把所有点都遍历完了 再判断哪条路最短
如果向量是单向的,那又更简单了
如果要用程序实现,一个可伸缩数据结构
一个循环就OK了 参考技术B 用Dijkstra算法,找到的是最短路径,返回的是从起点到终点的每个坐标:
import java.awt.Point;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
static List<Point> dij(final int[][] map, int startX, int startY, int endX, int endY)
int w = map.length;
int h = map[0].length;
final int[][] dist = new int[w][h];
Point[][] previous = new Point[w][h];
for (int i = 0; i < map.length; i++)
for (int j = 0; j < map[i].length; j++)
dist[i][j] = Integer.MAX_VALUE;
previous[i][j] = null;
dist[startX][startY]=0;
Point[] Q = new Point[w * h];
for(int i=0;i<w;i++)
for(int j=0;j<h;j++)
Q[(i*h)+j]=new Point(i, j);
class Comp implements Comparator<Point>
public int compare(Point o1, Point o2)
if (o1 == o2)
return 0;
if (o1 == null)
return -10000;
if (o2 == null)
return 10000;
return dist[o2.x][o2.y] - dist[o1.x][o1.y];
Comp comp = new Comp();
int lastElement = w * h - 1;
while (lastElement >= 0)
Arrays.sort(Q, 0, lastElement + 1, comp);
Point p = Q[lastElement--];
if (p == null)
break;
for (int k = -1; k <= 1; k++)
for (int m = -1; m <= 1; m++)
if (k != 0 || m != 0)
Point neighbor = new Point(p.x + k, p.y + m);
if (p.x + k >= 0
&& p.y + m >= 0
&& p.x + k < w
&& p.y + m < h
&& map[p.x + k][p.y + m] == 0
&& Arrays.binarySearch(Q, 0, lastElement + 1,
neighbor, comp) >= 0)
int cost;
if(dist[p.x][p.y]==Integer.MAX_VALUE) cost = Integer.MAX_VALUE;
else cost = 1000 + dist[p.x][p.y];
if (cost < dist[p.x + k][p.y + m])
dist[p.x + k][p.y + m] = cost;
previous[p.x+k][p.y+m] = new Point(p.x, p.y);
Point start = new Point(startX, startY);
Point destination = new Point(endX, endY);
LinkedList<Point> llist = new LinkedList<Point>();
llist.add(destination);
Point movingPoint = new Point(destination);
while(!movingPoint.equals(start))
Point path = previous[movingPoint.x][movingPoint.y];
if(path==null) break;
llist.add(new Point(path));
movingPoint.setLocation(path);
Collections.reverse(llist);
return llist;
参考技术C 这好像是离散数学里的最短路径算法吧
以上是关于1091.二维矩阵中的最短路径的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 1091 二进制矩阵中的最短路径问题[BFS 队列] HERODING的LeetCode之路