题目描述
宝宝和妈妈参加亲子游戏,在一个二维矩阵(N*N)的格子地图上,宝宝和妈妈抽签决定各自的位置,地图上每个格子有不同的糖果数量,部分格子有障碍物。
游戏规则是妈妈必须在最短的时间(每个单位时间只能走一步)到达宝宝的位置,路上的所有糖果都可以拿走,不能走障碍物的格子,只能上下左右走。
请问妈妈在最短到达宝宝位置的时间内最多拿到多少糖果(优先考虑最短时间到达的情况下尽可能多拿糖果)。
输入描述
第一行输入为 N,N 表示二维矩阵的大小
之后 N 行,每行有 N 个值,表格矩阵每个位置的值,其中:
-
-3:妈妈
-
-2:宝宝
-
-1:障碍
-
≥0:糖果数(0表示没有糖果,但是可以走)
输出描述
输出妈妈在最短到达宝宝位置的时间内最多拿到多少糖果,行末无多余空格
备注
地图最大 50*50
用例
输入 | 4 |
---|---|
输出 | 9 |
说明 |
输入 | 4 |
---|---|
输出 | -1 |
说明 |
题目解析
- 1.
首先,我们需要找到妈妈和宝宝的位置。
- 2.
然后,我们可以使用广度优先搜索(BFS)算法来寻找从妈妈到宝宝的最短路径。在搜索过程中,我们需要记录每个位置的糖果数量。
- 3.
对于每个位置,我们可以选择上下左右四个方向进行搜索。如果下一个位置是障碍物或者已经访问过,则跳过该位置。否则,将该位置加入队列中,并更新该位置的糖果数量。
- 4.
最后,返回到达宝宝位置时的最大糖果数量。如果没有找到路径,则返回-1。
JS算法源码
const rl = require("readline").createInterface({ input: process.stdin });
const readline = async () => (await rl[Symbol.asyncIterator]().next()).value;
(async function () {
const n = parseInt(await readline());
const candy = new Array(n).fill(0).map(() => new Array(n).fill(-1));
let queue = [];
const matrix = [];
for (let i = 0; i < n; i++) {
matrix.push((await readline()).split(" ").map(Number));
for (let j = 0; j < n; j++) {
if (matrix[i][j] == -3) {
candy[i][j] = 0;
queue.push([i, j]);
}
}
}
let ans = -1;
const offsets = [
[-1, 0],
[1, 0],
[0, -1],
[0, 1],
];
while (queue.length > 0) {
const newQueue = [];
let flag = false;
for (let [x, y] of queue) {
for (let [offsetX, offsetY] of offsets) {
const newX = x + offsetX;
const newY = y + offsetY;
if (
newX < 0 ||
newX >= n ||
newY < 0 ||
newY >= n ||
matrix[newX][newY] == -1
)
continue;
if (candy[newX][newY] == -1) {
newQueue.push([newX, newY]); // 加入当前扩散层
}
candy[newX][newY] = Math.max(
candy[newX][newY],
candy[x][y] + Math.max(0, matrix[newX][newY])
);
if (matrix[newX][newY] == -2) {
ans = candy[newX][newY];
flag = true;
}
}
}
if (flag) break;
queue = newQueue;
}
console.log(ans);
})();
Java算法源码
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
static int n;
static int[][] matrix;
static int[][] candy;
static int[][] offsets = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
matrix = new int[n][n];
candy = new int[n][n];
LinkedList<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
candy[i][j] = -1;
matrix[i][j] = sc.nextInt();
// 妈妈的位置
if (matrix[i][j] == -3) {
candy[i][j] = 0;
queue.add(i * n + j); // 二维坐标一维化
}
}
}
// 记录题解
int ans = -1;
// bfs 按层扩散
while (!queue.isEmpty()) {
// 记录当前扩散层的点
LinkedList<Integer> newQueue = new LinkedList<>();
// 当前层是否有宝宝所在的点
boolean flag = false;
for (int pos : queue) {
// 源点坐标
int x = pos / n;
int y = pos % n;
// 向四个方向扩散
for (int[] offset : offsets) {
// 当前扩散点坐标
int newX = x + offset[0];
int newY = y + offset[1];
// 当前扩散点坐标越界,或者扩散点是墙,则无法扩散
if (newX < 0 || newX >= n || newY < 0 || newY >= n || matrix[newX][newY] == -1) continue;
// 当前扩散点坐标对应的糖果数量为-1,说明对应扩散点坐标位置还没有加入到当前扩散层
if (candy[newX][newY] == -1) {
newQueue.addLast(newX * n + newY); // 加入当前扩散层
}
// 当前扩散点可能会被多个源点扩散到,因此比较保留扩散过程中带来的较大糖果数
// candy[newX][newY] 记录的是当前扩散点获得的糖果数
// candy[x][y] + Math.max(0, matrix[newX][newY]) 记录的是从源点(x,y)带来的糖果数 + (newX,newY)位置原本的糖果数
candy[newX][newY] =
Math.max(candy[newX][newY], candy[x][y] + Math.max(0, matrix[newX][newY]));
// 如果当前扩散点是宝宝位置,则可以停止后续层级的bfs扩散,因为已经找到宝宝的最短路径长度(即扩散层数)
if (matrix[newX][newY] == -2) {
ans = candy[newX][newY];
flag = true;
}
}
}
// 已经找到去宝宝位置的最短路径和最大糖果数,则终止bfs
if (flag) break;
// 否则继续
queue = newQueue;
}
System.out.println(ans);
}
}
Python算法源码
def bfs(matrix, n):
candy = [[-1] * n for _ in range(n)]
queue = []
for i in range(n):
for j in range(n):
if matrix[i][j] == -3:
candy[i][j] = 0
queue.append((i, j))
directions = ((0, -1), (0, 1), (-1, 0), (1, 0))
ans = -1
while len(queue) > 0:
newQueue = []
flag = False
for x, y in queue:
for offsetX, offsetY in directions:
newX = x + offsetX
newY = y + offsetY
if newX < 0 or newX >= n or newY < 0 or newY >= n or matrix[newX][newY] == -1:
continue
if candy[newX][newY] == -1:
newQueue.append((newX, newY))
candy[newX][newY] = max(candy[newX][newY], candy[x][y] + max(0, matrix[newX][newY]))
if matrix[newX][newY] == -2:
ans = candy[newX][newY]
flag = True
if flag:
break
queue = newQueue
return ans
n = int(input())
matrix = [list(map(int, input().split())) for _ in range(n)]
print(bfs(matrix, n))
C算法源码
#include <stdio.h>
#include <stdlib.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))
typedef struct ListNode {
int ele;
struct ListNode *next;
} ListNode;
typedef struct LinkedList {
int size;
ListNode *head;
ListNode *tail;
} LinkedList;
LinkedList *new_LinkedList() {
LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
link->size = 0;
link->head = NULL;
link->tail = NULL;
return link;
}
void addLast_LinkedList(LinkedList *link, int ele) {
ListNode *node = (ListNode *) malloc(sizeof(ListNode));
node->ele = ele;
node->next = NULL;
if (link->size == 0) {
link->head = node;
link->tail = node;
} else {
link->tail->next = node;
link->tail = node;
}
link->size++;
}
int main() {
int n;
scanf("%d", &n);
int **matrix = (int **) malloc(n * sizeof(int *));
int **candy = (int **) malloc(n * sizeof(int *));
for (int i = 0; i < n; i++) {
matrix[i] = (int *) malloc(n * sizeof(int));
candy[i] = (int *) malloc(n * sizeof(int));
}
LinkedList *queue = new_LinkedList();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
candy[i][j] = -1;
scanf("%d", &matrix[i][j]);
if (matrix[i][j] == -3) {
candy[i][j] = 0;
addLast_LinkedList(queue, i * n + j);
}
}
}
int offsets[4][2] = {{-1, 0},
{1, 0},
{0, -1},
{0, 1}};
int ans = -1;
while (queue->size > 0) {
LinkedList *newQueue = new_LinkedList();
int flag = 0;
ListNode *cur = queue->head;
while (cur != NULL) {
int x = cur->ele / n;
int y = cur->ele % n;
for (int i = 0; i < 4; i++) {
int newX = x + offsets[i][0];
int newY = y + offsets[i][1];
if (newX < 0 || newX >= n || newY < 0 || newY >= n || matrix[newX][newY] == -1) continue;
if (candy[newX][newY] == -1) {
addLast_LinkedList(newQueue, newX * n + newY);
}
int remain = MAX(0, matrix[newX][newY]);
candy[newX][newY] = MAX(candy[newX][newY], candy[x][y] + remain);
if (matrix[newX][newY] == -2) {
ans = candy[newX][newY];
flag = 1;
}
}
cur = cur->next;
}
if (flag) break;
queue = newQueue;
}
printf("%d\n", ans);
for (int i = 0; i < n; i++) {
free(matrix[i]);
free(candy[i]);
}
free(matrix);
free(candy);
free(queue);
return 0;
}