给定一个 n×m 的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中 0 表示可以走的路,1 表示不可通过的墙壁。
最初,有一个人位于左上角 (1,1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角 (n,m) 处,至少需要移动多少次
数据保证 (1,1) 处和 (n,m) 处的数字为 0,且一定至少存在一条通路。
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含 m 个整数(0 或 1),表示完整的二维数组迷宫。
输出一个整数,表示从左上角移动至右下角的最少移动次数。
1≤n,m≤100
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
8
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
//通过循环来进行组合,分别表示向左向右向上向下
static int[] dx = { 1, -1, 0, 0 };
static int[] dy = { 0, 0, 1, -1 };
static int[][] map = null;//定义一个二维数组用来存图中的每一个坐标是可以走的0,还是不可以走的墙1
static int[][] d = null;//定义一个二维数组用来存储移动次数
static int n, m;
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
map = new int[n][m];
d = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = sc.nextInt();
}
}
System.out.println(bfs());
}
//宽搜
public static int bfs() {
//定义一个队列
Queue q = new LinkedList<>();
//offer:添加一个元素并返回true,如果队列已满,则返回false
q.offer(new point(0, 0));
while (!q.isEmpty()) {
//poll:移除并返问队列头部的元素,如果队列为空,则返回null
point point = q.poll();
//如果遍历到了(m-1,n-1)
if (point.x == n - 1 && point.y == m - 1) {
break;
}
//如果还未遍历到了(m-1,n-1)
//用坐标表示向上下左右
//向上:x-1,y 向下:x+1,y 向左:x,y-1 向右:x,y+1
//用循环来表示分别向上向下向左向右
for (int i = 0; i < 4; i++) {
int x = point.x + dx[i];
int y = point.y + dy[i];
//如果(x-1,y-1)这个坐标还未到(m-1,n-1)终点,并且还在所给的map中,并且不是墙,并且还未走过
if (x >= 0 && x < n && y >= 0 && y < m && map[x][y] == 0 && d[x][y] == 0) {
//满足以上要求,就更新一下d,即累加移动次数到新的这个点上
//offer:添加一个元素并返回true,如果队列已满,则返回false
q.offer(new point(x, y));
//记录移动次数
d[x][y] = d[point.x][point.y] + 1;
}
}
}
//最后把右下角的点中存储的移动次数输出来就可以了
return d[n - 1][m - 1];
}
}
//定义point类,包含属性行x,列y
class point {
int x;
int y;
public point(int x, int y) {
this.x = x;
this.y = y;
}
}
class point {
int x;
int y;
public point(int x, int y) {
this.x = x;
this.y = y;
}
}
//通过循环来进行组合,分别表示向左向右向上向下,具体使用在下面
static int[] dx = { 1, -1, 0, 0 };
static int[] dy = { 0, 0, 1, -1 };
static int[][] map = null;//定义一个二维数组用来存图中的每一个坐标是可以走的0,还是不可以走的墙1
static int[][] d = null;//定义一个二维数组用来存储移动次数
static int n, m;//(n-1,m-1)为最右下角的点
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
map = new int[n][m];
d = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = sc.nextInt();
}
}
System.out.println(bfs());
}
public static int bfs() {
//定义一个队列
Queue q = new LinkedList<>();
//offer:添加一个元素并返回true,如果队列已满,则返回false
q.offer(new point(0, 0));
while (!q.isEmpty()) {
//poll:移除并返问队列头部的元素,如果队列为空,则返回null
point point = q.poll();
//如果遍历到了(m-1,n-1)
if (point.x == n - 1 && point.y == m - 1) {
break;
}
//如果还未遍历到了(m-1,n-1)
//用坐标表示向上下左右
//向上:x-1,y 向下:x+1,y 向左:x,y-1 向右:x,y+1
//用循环来表示分别向上向下向左向右
for (int i = 0; i < 4; i++) {
int x = point.x + dx[i];
int y = point.y + dy[i];
//如果(x-1,y-1)这个坐标还未到(m-1,n-1)终点,并且还在所给的map中,并且不是墙,并且还未走过
if (x >= 0 && x < n && y >= 0 && y < m && map[x][y] == 0 && d[x][y] == 0) {
//满足以上要求,就更新一下d,即累加移动次数到新的这个点上
//offer:添加一个元素并返回true,如果队列已满,则返回false
q.offer(new point(x, y));
//记录移动次数
d[x][y] = d[point.x][point.y] + 1;
}
}
}
//最后把右下角的点中存储的移动次数输出来就可以了
return d[n - 1][m - 1];
}
}
Queue q = new LinkedList<>();
q.offer(new point(0, 0));
while (!q.isEmpty()) {
//poll:移除并返问队列头部的元素,如果队列为空,则返回null
point point = q.poll();
//如果遍历到了(m-1,n-1)
if (point.x == n - 1 && point.y == m - 1) {
break;
}
static int[] dx = { 1, -1, 0, 0 };
static int[] dy = { 0, 0, 1, -1 };
当i=0时:
x = point.x + dx[0],即x = point.x + 1
y = point.y + dy[0],即y = point.y + 0
(x+1,y)表示向下移动
当i=1时:
x = point.x + dx[1],即x = point.x - 1
y = point.y + dy[1],即y = point.y + 0
(x+1,y)表示向上移动
当i=2时:
x = point.x + dx[2],即x = point.x + 0
y = point.y + dy[2],即y = point.y + 1
(x+1,y)表示向右移动
当i=3时:
x = point.x + dx[3],即x = point.x + 0
y = point.y + dy[3],即y = point.y - 1
(x+1,y)表示向左移动
q.offer(new point(x, y));
//记录移动次数
d[x][y] = d[point.x][point.y] + 1;
//宽搜
public static int bfs() {
//定义一个队列
Queue q = new LinkedList<>();
//offer:添加一个元素并返回true,如果队列已满,则返回false
q.offer(new point(0, 0));
while (!q.isEmpty()) {
//poll:移除并返问队列头部的元素,如果队列为空,则返回null
point point = q.poll();
//如果遍历到了(m-1,n-1)
if (point.x == n - 1 && point.y == m - 1) {
break;
}
//如果还未遍历到了(m-1,n-1)
//用坐标表示向上下左右
//向上:x-1,y 向下:x+1,y 向左:x,y-1 向右:x,y+1
//用循环来表示分别向上向下向左向右
for (int i = 0; i < 4; i++) {
int x = point.x + dx[i];
int y = point.y + dy[i];
//如果(x-1,y-1)这个坐标还未到(m-1,n-1)终点,并且还在所给的map中,并且不是墙,并且还未走过
if (x >= 0 && x < n && y >= 0 && y < m && map[x][y] == 0 && d[x][y] == 0) {
//满足以上要求,就更新一下d,即累加移动次数到新的这个点上
//offer:添加一个元素并返回true,如果队列已满,则返回false
q.offer(new point(x, y));
//记录移动次数
d[x][y] = d[point.x][point.y] + 1;
}
}
}
//最后把右下角的点中存储的移动次数输出来就可以了
return d[n - 1][m - 1];
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
static int map[][];
static int count[][];
static int n;
static int m;
static int[] px = {0,0,1,-1};
static int[] py = {1,-1,0,0};
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
map = new int[n][m];
count = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = sc.nextInt();
}
}
System.out.println(bfs());
}
public static int bfs() {
Queue q = new LinkedList<>();
q.offer(new point(0,0));
while (!q.isEmpty()){
point point = q.poll();
if (point.x == n - 1 && point.y == m - 1){
break;
}
for (int i = 0; i < 4; i++) {
int x = point.x + px[i];
int y = point.y + py[i];
if (x < n && y < m && x >= 0 && y >= 0 && count[x][y] == 0 && map[x][y] == 0){
q.offer(new point(x,y));
count[x][y] = count[point.x][point.y] + 1;
}
}
}
return count[n-1][m-1];
}
}
class point{
int x;
int y;
public point(int x, int y) {
this.x = x;
this.y = y;
}
}