【备战秋招】每日一题:2023.05-B卷-华为OD机试 - 宜居星球改造计划

为了更好的阅读体检,可以查看我的算法学习网
本题在线评测链接:P1358

题目描述

2 X X X 2XXX 2XXX年,人类通过对火星的大气进行宜居改造分析,使得火星已在理论上具备人类宜居的条件;

由于技术原因,无法一次性将火星大气全部改造,只能通过局部处理形式;

假设将火星待改造的区域为 r o w ∗ c o l u m n row*column rowcolumn的网格,每个网格有 3 3 3个值,宜居区、可改造区、死亡区,使用 Y E S YES YES N O NO NO N A NA NA代替, Y E S YES YES表示该网格已经完成大气改造, N O NO NO表示该网格未进行改造,后期可进行改造, N A NA NA表示死亡区,不作为判断是否改造完的宜居,无法穿过;

初始化下,该区域可能存在多个宜居区,并目每个宜居区能同时在每个大阳日单位向上下左右四个方向的相邻格子进行扩散,自动将 4 4 4个方向相邻的真空区改造成宜居区:

请计算这个待改造区域的网格中,可改造区是否能全部成宜居区,如果可以,则返回改造的大阳日天教,不可以则返回 − 1 -1 1

输入描述

输入 r o w ∗ c o l u m n row*column rowcolumn个网格数据,每个网格值枚举值如下: Y E S YES YES N O NO NO N A NA NA;

样例:

Y E S YES YES Y E S YES YES N O NO NO

N O NO NO N O NO NO N O NO NO

N A NA NA N O NO NO Y E S YES YES

输出描述

可改造区是否能全部变成宜居区,如果可以,则返回改造的太阳日天数,不可以则返回 − 1 -1 1

备注

g r i d grid grid [ i ] [i] [i] [ j ] [j] [j]只有 3 3 3种情况, Y E S YES YES N O NO NO N A NA NA

- r o w row row g r i d . l e n g t h grid.length grid.length
- c o l u m n column column
g r i d [ i ] . l e n g t h grid[i].length grid[i].length
- 1 ≤ 1 \leq 1 r o w row row, c o l u m n ≤ 8 column \leq 8 column8

样例

输入

YES YES NO
NO NO NO
YES NO NO

输出

2

说明

进过2个太阳日,完成宜居改造。

输入

YES NO NO NO
NO NO NO NO
NO NO NO NO
NO NO NO NO

输出

6

说明

经过 6 6 6个太阳日,可完成改造。

输入

NO NA

输出

-1

说明

无改造初始条件,无法进行改造。

输入

YES NO NO YES
NO NO YES NO
NO YES NA NA
YES NO NA NO

输出

-1

说明

− 1 -1 1//右下角的区域,被周边三个死亡区挡住,无法实现改造。

思路

我们发现题目要求改造所有可改造区最小的日期。

因此题目可以分为两个问题:一、找到所有的可改造区。二、宜居区距离目标改造区的最短距离。

问题一解决方法:

很明显,题目可以抽象为给定 n ∗ m n*m nm的地图,以及多个起点,问能否通过起点找到所有可改造的区域。对于二维地图,给定特定起点,目标为找到指定点一类的问题,都可以使用 B F S BFS BFS或者 D F S DFS DFS。因为这两个搜索的主要目的就是找到所有可以搜查到的地方。那么这道题所谓的可以搜查到的地方便是可改造区,而不可搜查地方便是死亡区,我们遇到死亡区就直接跳过不搜索即可。

问题二解决方法:

我们首先了解到问题的解决方法便是 B F S BFS BFS或者 D F S DFS DFS

其次,我们将问题二转化一下变为:给定二维地图,给定起始点和终点,找到起始点到终点的最短距离。对于这一类的最短路题目,由于点与点之间的距离为1(宜居区到相邻可改造区域只需要一天),因此,可以直接使用 B F S BFS BFS去找到最短路。

类似题目推荐

代码

C++

#include <iostream>
#include <vector>
#include <queue>
#include <sstream>

using namespace std;

int getResult(vector<vector<string>>& matrix) {
    int row = matrix.size();
    int col = matrix[0].size();

    // 记录宜居取坐标位置
    queue<pair<int, int>> que;
    // 记录可改造区数量
    int need = 0;

    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            if (matrix[i][j] == "YES") {
                que.push({i, j});
            } else if (matrix[i][j] == "NO") {
                need += 1;
            }
        }
    }

    // 如果没有宜居区,则无法改造,直接返回-1
    if (que.empty()) {
        return -1;
    }
    // 如果全是宜居区,则无需改造,直接返回0
    else if (que.size() == row * col) {
        return 0;
    }

    // 记录花费的天数
    int day = 0;
    // 上,下,左,右四个方向的偏移量
    vector<pair<int, int>> offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    // 图的多源BFS模板
    while (!que.empty() && need > 0) {
        queue<pair<int, int>> newQueue;

        while (!que.empty()) {
            pair<int, int> coordinates = que.front();
            que.pop();

            int x = coordinates.first;
            int y = coordinates.second;

            for (auto& offset : offsets) {
                // 上,下,左,右四个方向扩散
                int newX = x + offset.first;
                int newY = y + offset.second;

                // 如果新位置没有越界,且为NO,则可以被改造
                if (newX >= 0 && newX < row && newY >= 0 && newY < col && matrix[newX][newY] == "NO") {
                    matrix[newX][newY] = "YES";
                    newQueue.push({newX, newY});
                    need -= 1;
                }
            }
        }

        day += 1;
        que = newQueue;
    }

    if (need == 0) {
        return day;
    } else {
        return -1;
    }
}

int main() {
    vector<vector<string>> matrix;

    string line;
    while (getline(cin, line)) {
        istringstream iss(line);
        vector<string> row;
        string value;
        while (iss >> value) {
            row.push_back(value);
        }
        matrix.push_back(row);
    }

    cout << getResult(matrix) << endl;

    return 0;
}

python

# 算法入口
def getResult(matrix):
    row = len(matrix)
    col = len(matrix[0])

    # 记录宜居取坐标位置
    queue = []
    # 记录可改造区数量
    need = 0

    for i in range(row):
        for j in range(col):
            if matrix[i][j] == "YES":
                queue.append([i, j])
            elif matrix[i][j] == "NO":
                need += 1

    # 如果没有宜居区,则无法改造,直接返回-1
    if len(queue) == 0:
        return -1
    # 如果全是宜居区,则无需改造,直接返回0
    elif len(queue) == row * col:
        return 0

    # 记录花费的天数
    day = 0
    # 上,下,左,右四个方向的偏移量
    offsets = ((-1, 0), (1, 0), (0, -1), (0, 1))

    # 图的多源BFS模板
    while len(queue) > 0 and need > 0:
        newQueue = []

        for x, y in queue:
            for offsetX, offsetY in offsets:
                # 上,下,左,右四个方向扩散
                newX = x + offsetX
                newY = y + offsetY

                # 如果新位置没有越界,且为NO,则可以被改造
                if row > newX >= 0 and col > newY >= 0 and matrix[newX][newY] == "NO":
                    matrix[newX][newY] = "YES"
                    newQueue.append([newX, newY])
                    need -= 1

        day += 1
        queue = newQueue

    if need == 0:
        return day
    else:
        return -1


# 输入获取
matrix = []
while True:
    try:
        line = input()
        matrix.append(line.split())
    except:
        break
print(getResult(matrix), end = "\n")

Java

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        ArrayList<ArrayList<String>> matrix = new ArrayList<>();

        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            String[] row = line.split(" ");
            ArrayList<String> rowList = new ArrayList<>();
            for (String value : row) {
                rowList.add(value);
            }
            matrix.add(rowList);
        }

        System.out.println(getResult(matrix));
    }

    public static int getResult(ArrayList<ArrayList<String>> matrix) {
        int row = matrix.size();
        int col = matrix.get(0).size();

        // 记录宜居取坐标位置
        Queue<int[]> queue = new LinkedList<>();
        // 记录可改造区数量
        int need = 0;

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (matrix.get(i).get(j).equals("YES")) {
                    queue.add(new int[]{i, j});
                } else if (matrix.get(i).get(j).equals("NO")) {
                    need += 1;
                }
            }
        }

        // 如果没有宜居区,则无法改造,直接返回-1
        if (queue.isEmpty()) {
            return -1;
        }
        // 如果全是宜居区,则无需改造,直接返回0
        else if (queue.size() == row * col) {
            return 0;
        }

        // 记录花费的天数
        int day = 0;
        // 上,下,左,右四个方向的偏移量
        int[][] offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

        // 图的多源BFS模板
        while (!queue.isEmpty() && need > 0) {
            Queue<int[]> newQueue = new LinkedList<>();

            for (int[] coordinates : queue) {
                int x = coordinates[0];
                int y = coordinates[1];

                for (int[] offset : offsets) {
                    // 上,下,左,右四个方向扩散
                    int newX = x + offset[0];
                    int newY = y + offset[1];

                    // 如果新位置没有越界,且为NO,则可以被改造
                    if (newX >= 0 && newX < row && newY >= 0 && newY < col && matrix.get(newX).get(newY).equals("NO")) {
                        matrix.get(newX).set(newY, "YES");
                        newQueue.add(new int[]{newX, newY});
                        need -= 1;
                    }
                }
            }

            day += 1;
            queue = newQueue;
        }

        if (need == 0) {
            return day;
        } else {
            return -1;
        }
    }
}

Go

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	matrix := [][]string{}

	for scanner.Scan() {
		line := scanner.Text()
		row := strings.Split(line, " ")
		matrixRow := []string{}
		for _, value := range row {
			matrixRow = append(matrixRow, value)
		}
		matrix = append(matrix, matrixRow)
	}

	fmt.Println(getResult(matrix))
}

func getResult(matrix [][]string) int {
	row := len(matrix)
	col := len(matrix[0])

	// 记录宜居取坐标位置
	queue := [][]int{}
	// 记录可改造区数量
	need := 0

	for i := 0; i < row; i++ {
		for j := 0; j < col; j++ {
			if matrix[i][j] == "YES" {
				queue = append(queue, []int{i, j})
			} else if matrix[i][j] == "NO" {
				need += 1
			}
		}
	}

	// 如果没有宜居区,则无法改造,直接返回-1
	if len(queue) == 0 {
		return -1
	}
	// 如果全是宜居区,则无需改造,直接返回0
	if len(queue) == row*col {
		return 0
	}

	// 记录花费的天数
	day := 0
	// 上,下,左,右四个方向的偏移量
	offsets := [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}

	// 图的多源BFS模板
	for len(queue) > 0 && need > 0 {
		newQueue := [][]int{}

		for _, coordinates := range queue {
			x := coordinates[0]
			y := coordinates[1]

			for _, offset := range offsets {
				// 上,下,左,右四个方向扩散
				newX := x + offset[0]
				newY := y + offset[1]

				// 如果新位置没有越界,且为NO,则可以被改造
				if newX >= 0 && newX < row && newY >= 0 && newY < col && matrix[newX][newY] == "NO" {
					matrix[newX][newY] = "YES"
					newQueue = append(newQueue, []int{newX, newY})
					need -= 1
				}
			}
		}

		day += 1
		queue = newQueue
	}

	if need == 0 {
		return day
	} else {
		return -1
	}
}

Js

function getResult(matrix) {
    let row = matrix.length;
    let col = matrix[0].length;

    // 记录宜居取坐标位置
    let queue = [];
    // 记录可改造区数量
    let need = 0;

    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            if (matrix[i][j] === "YES") {
                queue.push([i, j]);
            } else if (matrix[i][j] === "NO") {
                need += 1;
            }
        }
    }

    // 如果没有宜居区,则无法改造,直接返回-1
    if (queue.length === 0) {
        return -1;
    }
    // 如果全是宜居区,则无需改造,直接返回0
    else if (queue.length === row * col) {
        return 0;
    }

    // 记录花费的天数
    let day = 0;
    // 上,下,左,右四个方向的偏移量
    let offsets = [[-1, 0], [1, 0], [0, -1], [0, 1]];

    // 图的多源BFS模板
    while (queue.length > 0 && need > 0) {
        let newQueue = [];

        for (let [x, y] of queue) {
            for (let [offsetX, offsetY] of offsets) {
                // 上,下,左,右四个方向扩散
                let newX = x + offsetX;
                let newY = y + offsetY;

                // 如果新位置没有越界,且为NO,则可以被改造
                if (newX >= 0 && newX < row && newY >= 0 && newY < col && matrix[newX][newY] === "NO") {
                    matrix[newX][newY] = "YES";
                    newQueue.push([newX, newY]);
                    need -= 1;
                }
            }
        }

        day += 1;
        queue = newQueue;
    }

    if (need === 0) {
        return day;
    } else {
        return -1;
    }
}

let readline = require('readline');
let rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let matrix = [];
rl.on('line', function (line) {
    let row = line.split(" ");
    matrix.push(row);
});

rl.on('close', function () {
    console.log(getResult(matrix));
});

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

塔子哥学算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值