题目描述
有M*N
的节点矩阵,每个节点可以向8个方向(上下左右及四个斜线防线)转发数据包,每个节点转发时会消耗固定时延,连续两个相同时延可以减少一个时延值(即当有K
个相同时延的节点连续转发时可以减少K-1
个时延值),求左上角(0,0)
开始转发数据包到右下角(M-1,N-1)
并转发出的最短时延。
输入描述
第一行两个数字,M,N
,接下来有M
行,每行有N
个数据,表示M*N
的矩阵。
输出描述
最短时延值
用例
输入 | 3 3 0 2 2 1 2 1 2 2 1 |
---|---|
输出 | 3 |
说明 | 无 |
输入 | 3 3 2 2 2 2 2 2 2 2 2 |
---|---|
输出 | 4 |
说明 | (2+2+2-(3-1)) |
Java
import java.util.*;
public class Main {
static int m, n; // 矩阵的行数和列数
static int[][] matrix; // 存储矩阵的二维数组
static int[][] offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; // 存储八个方向的偏移量
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
m = scanner.nextInt(); // 输入矩阵的行数
n = scanner.nextInt(); // 输入矩阵的列数
matrix = new int[m][n]; // 初始化矩阵的二维数组
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = scanner.nextInt(); // 输入矩阵的每个元素
}
}
List<Integer> res = new ArrayList<>(); // 存储所有到达终点的路径的延迟时间
Set<Integer> path = new HashSet<>(); // 存储当前路径中已经访问过的位置
path.add(0); // 将起点加入路径中
dfs(0, 0, 0, Integer.MAX_VALUE, path, res); // 从起点开始遍历矩阵
System.out.println(Collections.min(res)); // 输出所有到达终点的路径中的最小延迟时间
}
private static void dfs(int i, int j, int delay, int last, Set<Integer> path, List<Integer> res) {
int cur = matrix[i][j]; // 当前位置的值
boolean flag = cur == last; // 判断是否需要等待一秒
if (i == m - 1 && j == n - 1) { // 到达终点
delay += cur - (flag ? 1 : 0); // 更新延迟时间
res.add(delay); // 将当前的延迟时间加入结果列表
return;
}
for (int[] offset : offsets) { // 遍历八个方向
int new_i = i + offset[0]; // 新的行坐标
int new_j = j + offset[1]; // 新的列坐标
int pos = new_i * n + new_j; // 将二维坐标转换为一维坐标
if (new_i >= 0 && new_i < m && new_j >= 0 && new_j < n && !path.contains(pos)) { // 判断新的位置是否越界且是否已经访问过
path.add(pos); // 将新的位置加入路径中
dfs(new_i, new_j, delay + cur - (flag ? 1 : 0), cur, path, res); // 递归遍历新的位置
path.remove(pos); // 将新的位置从路径中删除,回溯到上一步
}
}
}
}
JavaScript
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let m, n;
let matrix = [];
let offsets = [[-1, 0], [1, 0], [0, -1], [0, 1], [-1, -1], [-1, 1], [1, -1], [1, 1]];
function dfs(i, j, delay, last, path, res) {
let cur = matrix[i][j];
let flag = cur === last;
if (i === m - 1 && j === n - 1) {
delay += cur - (flag ? 1 : 0);
res.push(delay);
return;
}
for (let offset of offsets) {
let new_i = i + offset[0];
let new_j = j + offset[1];
let pos = new_i * n + new_j;
if (new_i >= 0 && new_i < m && new_j >= 0 && new_j < n && !path.has(pos)) {
path.add(pos);
dfs(new_i, new_j, delay + cur - (flag ? 1 : 0), cur, path, res);
path.delete(pos);
}
}
}
rl.on('line', function (line) {
if (!m) {
[m, n] = line.split(' ').map(Number);
matrix = Array(m).fill().map(() => Array(n).fill(0));
} else {
let row = matrix.length - m;
matrix[row] = line.split(' ').map(Number);
if (row === m - 1) {
let res = [];
let path = new Set();
path.add(0);
dfs(0, 0, 0, Infinity, path, res);
console.log(Math.min(...res));
rl.close();
}
m--;
}
});
C++
#include <iostream>
#include <vector>
#include <unordered_set>
#include <climits>
#include <algorithm>
using namespace std;
int m, n; // 矩阵的行数和列数
vector<vector<int>> matrix; // 存储矩阵的二维向量
vector<vector<int>> offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; // 存储八个方向的偏移量
void dfs(int i, int j, int delay, int last, unordered_set<int>& path, vector<int>& res) {
int cur = matrix[i][j]; // 当前位置的值
bool flag = cur == last; // 判断是否需要等待一秒
if (i == m - 1 && j == n - 1) { // 到达终点
delay += cur - (flag ? 1 : 0); // 更新延迟时间
res.push_back(delay); // 将当前的延迟时间加入结果向量
return;
}
for (auto& offset : offsets) { // 遍历八个方向
int new_i = i + offset[0]; // 新的行坐标
int new_j = j + offset[1]; // 新的列坐标
int pos = new_i * n + new_j; // 将二维坐标转换为一维坐标
if (new_i >= 0 && new_i < m && new_j >= 0 && new_j < n && !path.count(pos)) { // 判断新的位置是否越界且是否已经访问过
path.insert(pos); // 将新的位置加入路径中
dfs(new_i, new_j, delay + cur - (flag ? 1 : 0), cur, path, res); // 递归遍历新的位置
path.erase(pos); // 将新的位置从路径中删除,回溯到上一步
}
}
}
int main() {
cin >> m >> n; // 输入矩阵的行数和列数
matrix.resize(m, vector<int>(n)); // 初始化矩阵的二维向量
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> matrix[i][j]; // 输入矩阵的每个元素
}
}
vector<int> res; // 存储所有到达终点的路径的延迟时间
unordered_set<int> path; // 存储当前路径中已经访问过的位置
path.insert(0); // 将起点加入路径中
dfs(0, 0, 0, INT_MAX, path, res); // 从起点开始遍历矩阵
cout << *min_element(res.begin(), res.end()) << endl; // 输出所有到达终点的路径中的最小延迟时间
return 0;
}
Python
m, n = map(int, input().split()) # 输入矩阵的行数和列数
matrix = [] # 存储矩阵的二维列表
for i in range(m):
row = list(map(int, input().split())) # 输入矩阵的每个元素
matrix.append(row)
offsets = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)] # 存储八个方向的偏移量
def dfs(i, j, delay, last, path, res):
cur = matrix[i][j] # 当前位置的值
flag = cur == last # 判断是否需要等待一秒
if i == m - 1 and j == n - 1: # 到达终点
delay += cur - (1 if flag else 0) # 更新延迟时间
res.append(delay) # 将当前的延迟时间加入结果列表
return
for offset in offsets: # 遍历八个方向
new_i = i + offset[0] # 新的行坐标
new_j = j + offset[1] # 新的列坐标
pos = new_i * n + new_j # 将二维坐标转换为一维坐标
if 0 <= new_i < m and 0 <= new_j < n and pos not in path: # 判断新的位置是否越界且是否已经访问过
path.add(pos) # 将新的位置加入路径中
dfs(new_i, new_j, delay + cur - (1 if flag else 0), cur, path, res) # 递归遍历新的位置
path.remove(pos) # 将新的位置从路径中删除,回溯到上一步
res = [] # 存储所有到达终点的路径的延迟时间
path = set([0]) # 存储当前路径中已经访问过的位置
dfs(0, 0, 0, float('inf'), path, res) # 从起点开始遍历矩阵
print(min(res)) # 输出所有到达终点的路径中的最小延迟时间