华为OD机试 - 宜居星球改造计划

题目描述

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

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

假设将火星待改造的区域为row*column的网格,每个网格有3个值,宜居区、可改造区、死亡区,使用YES、NO、NA代替,YES表示该网格已经完成大气改造,NO表示该网格未进行改造,后期可进行改造,NA表示死亡区,不作为判断是否改造完的宜居,无法穿过;

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

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

输入描述

输入row*column个网格数据,每个网格值枚举值如下:YES,NO,NA;

样例:

YES YES NO

NO NO NO

NA NO YES

输出描述

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

备注

grid[i][j]只有3种情况,YES、NO、NA

样例

输入

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个太阳日,可完成改造。

输入

NO NA

输出

-1

说明

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

输入

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

输出

-1

说明

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

思路

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

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

问题一解决方法:

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

问题二解决方法:

我们首先了解到问题的解决方法便是BFS或者DFS。

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

代码

C++

#include 
#include 
#include 
#include 

using namespace std;

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

    // 记录宜居取坐标位置
    queue> 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> offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

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

        while (!que.empty()) {
            pair 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> matrix;

    string line;
    while (getline(cin, line)) {
        istringstream iss(line);
        vector 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> matrix = new ArrayList<>();

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

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

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

        // 记录宜居取坐标位置
        Queue 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 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));
});
​

你可能感兴趣的:(华为od,算法,java,数据结构,python,c#,go)