问题描述
在一个大城市中,环卫工人小C和他的团队负责清理城市的生活垃圾。整个城市被分为了若干个区域,每个区域被划分为m行n列的网格。环卫工人需要将每个居民区的垃圾运输到最近的垃圾回收站。这个任务要求计算所有居民区垃圾送到回收站的最小总距离。
输入输出
第一行为两个整数m和n,表示网格的行数和列数,其中m和n的范围均为[1,300)。接下来m行表示区域的矩阵布局,每行元素间以空格分隔。网格元素为以下几种:
-
-1
表示该区域有障碍物,不可通行。 -
0
表示垃圾回收站。 -
1
表示居民区,需要收集垃圾。 -
2
表示空白区域,可以自由通行。
输出一个整数,表示将所有居民区的垃圾送到最近的垃圾回收站所需的最小距离和。如果无法到达垃圾回收站的居民区将被忽略。
输入:
4 4
1 2 -1 1
2 0 2 0
2 2 -1 2
1 2 1 1
输出:
11
输入:
2 3
0 -1 1
1 -1 2
输出:
1
解题思路
用bfs而不用dfs,因为dfs需要求出可到达的所有垃圾站距离后再取最小值,而bfs遇到的第一个垃圾站一定是最小的距离。
AC代码
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
static int n, m; // n行m列
static int[][] juzhen; // 存图
static int[][] nextTo = new int[][]{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 存方向
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
juzhen = new int[n][m];
Queue<Pos> queue = new LinkedList<>(); // 存所有居民区,即起点
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
juzhen[i][j] = scan.nextInt();
if (juzhen[i][j] == 1) {
queue.add(new Pos(i, j, 0));
}
}
}
int disc = 0; // 存总距离
for (Pos pos : queue) {
disc += bfs(pos.x, pos.y);
}
System.out.println(disc);
}
/**
* bfs遍历返回到垃圾回收站的最短距离
*/
private static int bfs(int x, int y) {
Queue<Pos> q = new LinkedList<>();
q.add(new Pos(x, y, 0)); // 居民区到自身距离为0
boolean[][] visited = new boolean[n][m]; // 记录是否访问过
visited[x][y] = true;
while (!q.isEmpty()) {
Pos pos = q.poll();
for (int i = 0; i < 4; i++) {
int xx = pos.x + nextTo[i][0];
int yy = pos.y + nextTo[i][1];
if (xx >= 0 && xx < n && yy >= 0 && yy < m) {
if (!visited[xx][yy] && juzhen[xx][yy] != -1) {
if (juzhen[xx][yy] == 0) {
return pos.disc + 1;
}
q.add(new Pos(xx, yy, pos.disc + 1));
}
}
}
}
return 0;
}
}
class Pos {
public int x, y, disc; // 坐标和与居民区的距离
public Pos(int x, int y, int disc) {
this.x = x;
this.y = y;
this.disc = disc;
}
}
(by 归忆)