小C的城市清洁(多源最短路径&java&华为0911秋招笔试题一)

问题描述

在一个大城市中,环卫工人小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 归忆)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

归忆_AC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值