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.二维矩阵中的最短路径的主要内容,如果未能解决你的问题,请参考以下文章

1091. 二进制矩阵中的最短路径

二进制矩阵中的最短路径(力扣第1091题)

LeetCode 1091 二进制矩阵中的最短路径问题[BFS 队列] HERODING的LeetCode之路

[JavaScript 刷题] 搜索 - 计算在网格中从原点到特定点的最短路径长度 Leetcode 1091

求java实现矩阵图上任意两点的最短路径源码

弗洛伊德(Floyd)算法求图的最短路径