园区某部门举办了Family Day,邀请员工及其家属参加。将公司园区视为一个矩形,起始园区设置在左上角,终点园区设置在右下角。家属参观园区时,只能向右和向下园区前进,求从起始园区到终点园区会有多少条不同的参观路径。
输出为不同的路径数量。
3 3
0 0 0
0 1 0
0 0 0
2
本题可以使用深度优先搜索(DFS)或动态规划(DP)来解题。
DFS的每一条递归分支都对应一条路径。如果某个递归分支可以走到终点位置,那么说明该递归分支对应的路径可达终点。递归进入下一个位置的条件是:
由于本题限定只能从当前位置向下或者向右进入下一个位置,因此不用担心走回头路的问题,即不用建立visited表记录走过的位置。
注意:如果地图矩阵数量级过大,基于递归实现的DFS可能会发生StackOverFlow异常,因此更推荐使用基于栈结构实现的DFS。此外,DFS在大数量级情况下可能会超时。
更优的解法是利用动态规划。我们可以定义一个dp二维数组,dp[i][j]
的含义是:从坐标(0,0)
到达坐标(i, j)
的路径数。
由于只能向下或者向右运动,因此到达一个坐标点,可能来自其上方,也可能来自其左方。因此:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
即:
(i-1,j)
的路径有dp[i-1][j]
条,那么到达(i,j)
的路径也有dp[i-1][j]
条;(i, j-1)
的路径有dp[i][j-1]
条,那么到达(i,j)
的路径也有dp[i][j-1]
条。初始化:
dp[0][0]
初始化时,需要注意(0,0)
坐标位置是否可以参观。如果不可以参观,则到达(0,0)
的路径为0条,否则为1条。注意事项:
通过动态规划的方法,可以有效地计算出从起始园区到终点园区的不同路径数量。
要解决这个网格路径计数的问题,可以采用以下几种方法:动态规划、基于递归的深度优先搜索(DFS)和基于栈的DFS。每种方法都有其独特的实现方式和适用场景。
输入处理:
n
和列数m
。matrix
中,其中0
表示可通行,1
表示障碍物。初始化动态规划表:
dp
,用于存储到达每个位置的路径数量。dp[0][0]
初始化为1
,表示只有一种方式到达起点(即不移动)。填充动态规划表:
(i, j)
,如果不是障碍物,就将来自上方和左方的路径数相加,得到当前位置的路径数。dp[i][j] += dp[i-1][j]
。dp[i][j] += dp[i][j-1]
。结果输出:
dp[n-1][m-1]
即为从起点到终点的所有可能路径的数量。时间复杂度:
空间复杂度:
dp
。输入处理:
定义移动偏移量:
offsets = ((1, 0), (0, 1))
,表示从当前位置向下和向右移动。初始化路径数量:
ans
来记录到达终点的路径数量。递归函数dfs(x, y)
:
(n-1, m-1)
,则增加路径数量ans
,并返回。(newX, newY)
。dfs(newX, newY)
。调用递归函数:
(0,0)
开始递归搜索,前提是起点是可通行的。结果输出:
ans
。时间复杂度:
空间复杂度:
输入处理:
定义移动偏移量:
offsets = ((1, 0), (0, 1))
。初始化路径数量:
ans
记录到达终点的路径数量。栈初始化:
stack
,用于显式模拟递归调用的过程。pos = x*m + y
)并压入栈中。栈式DFS循环:
x
和列号y
。ans
,并继续处理。(newX, newY)
。结果输出:
ans
。时间复杂度:
空间复杂度:
根据具体需求和网格大小的不同,可以选择最适合当前场景的算法。在大多数情况下,动态规划是首选算法,而DFS方法适用于特定的小规模应用或需要明确路径的情况。
以下是基于动态规划(DP)、递归实现的深度优先搜索(DFS)以及基于栈实现的深度优先搜索(DFS)的代码,并附有详细注释和讲解。
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// 读取输入:园区的长n(行数)和宽m(列数)
const [n, m] = (await readline()).split(" ").map(Number);
// 读取地图矩阵:0表示可以参观,1表示不能参观
const matrix = [];
for (let i = 0; i < n; i++) {
matrix.push((await readline()).split(" ").map(Number));
}
// 如果起点(0,0)或终点(n-1, m-1)不能参观,则没有路径
if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
console.log(0);
return;
}
// 初始化dp数组:dp[i][j]表示从(0,0)到(i,j)的路径数
const dp = new Array(n).fill(0).map(() => new Array(m).fill(0));
dp[0][0] = 1; // 起点到起点只有一条路径
// 动态规划填充dp数组
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
// 如果当前格子不能参观,则跳过
if (matrix[i][j] == 1) continue;
// 如果可以从上方格子到达当前格子
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
// 如果可以从左方格子到达当前格子
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
// 输出从起点到终点的路径数
console.log(dp[n - 1][m - 1]);
})();
代码讲解:
n
和宽m
。0
表示可以参观,1
表示不能参观。(0,0)
或终点(n-1, m-1)
不能参观,则直接输出0
,因为没有路径。dp
:
dp[i][j]
表示从起点(0,0)
到(i,j)
的路径数。dp[0][0] = 1
,因为起点到起点只有一条路径。(i,j)
,如果可以从上方(i-1,j)
到达,则dp[i][j] += dp[i-1][j]
。(i,j-1)
到达,则dp[i][j] += dp[i][j-1]
。dp[n-1][m-1]
即为从起点到终点的路径数。const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// 读取输入:园区的长n(行数)和宽m(列数)
const [n, m] = (await readline()).split(" ").map(Number);
// 读取地图矩阵:0表示可以参观,1表示不能参观
const matrix = [];
for (let i = 0; i < n; i++) {
matrix.push((await readline()).split(" ").map(Number));
}
// 向下、向右的偏移量
const offsets = [
[1, 0], // 向下
[0, 1], // 向右
];
// 记录题解:从起点到终点的路径数
let ans = 0;
// 深度优先搜索函数
function dfs(x, y) {
// 如果当前分支可以走到终点,则对应分支路径可行
if (x == n - 1 && y == m - 1) {
ans++;
return;
}
// 从当前位置(x, y)向下或者向右走
for (let [offsetX, offsetY] of offsets) {
// 新位置(newX, newY)
const newX = x + offsetX;
const newY = y + offsetY;
// 如果新位置没有越界且新位置可以参观,则进入
if (
newX >= 0 &&
newX < n &&
newY >= 0 &&
newY < m &&
matrix[newX][newY] == 0
) {
dfs(newX, newY);
}
}
}
// 从(0,0)位置开始深搜,深搜对应的每条分支都对应一条路径
if (matrix[0][0] == 0) {
dfs(0, 0);
}
// 输出结果
console.log(ans);
})();
代码讲解:
n
和宽m
。0
表示可以参观,1
表示不能参观。offsets
。(0,0)
开始递归搜索。(n-1, m-1)
,则路径数ans++
。ans
即为从起点到终点的路径数。const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// 读取输入:园区的长n(行数)和宽m(列数)
const [n, m] = (await readline()).split(" ").map(Number);
// 读取地图矩阵:0表示可以参观,1表示不能参观
const matrix = [];
for (let i = 0; i < n; i++) {
matrix.push((await readline()).split(" ").map(Number));
}
// 向下、向右的偏移量
const offsets = [
[1, 0], // 向下
[0, 1], // 向右
];
// 记录题解:从起点到终点的路径数
let ans = 0;
// 基于栈的深度优先搜索函数
function dfs() {
const stack = [];
// 如果起点可以参观,则将其压入栈
if (matrix[0][0] == 0) {
stack.push(0); // 使用一维索引表示位置
}
// 栈不为空时继续搜索
while (stack.length > 0) {
const pos = stack.pop();
// 将一维索引转换为二维坐标
const y = pos % m;
const x = (pos - y) / m;
// 如果当前位置是终点,则路径数加1
if (x == n - 1 && y == m - 1) {
ans++;
continue;
}
// 从当前位置向下或向右移动
for (let [offsetX, offsetY] of offsets) {
const newX = x + offsetX;
const newY = y + offsetY;
// 如果新位置合法且可以参观,则压入栈
if (
newX >= 0 &&
newX < n &&
newY >= 0 &&
newY < m &&
matrix[newX][newY] == 0
) {
stack.push(newX * m + newY); // 使用一维索引表示新位置
}
}
}
}
// 从(0,0)位置开始深搜
dfs();
// 输出结果
console.log(ans);
})();
代码讲解:
n
和宽m
。0
表示可以参观,1
表示不能参观。offsets
。(0,0)
压入栈。(n-1, m-1)
,则路径数ans++
。ans
即为从起点到终点的路径数。O(n*m)
。import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 读取行数n,表示网格的长度
int m = sc.nextInt(); // 读取列数m,表示网格的宽度
int[][] matrix = new int[n][m]; // 创建网格矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = sc.nextInt(); // 读取每个位置的值,0表示可通过,1表示障碍物
}
}
// 检查起点或终点是否为障碍物,如果是,则无法到达终点,输出0
if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
System.out.println(0);
return;
}
long[][] dp = new long[n][m]; // 创建动态规划数组,用于存储到达每个位置的路径数量
dp[0][0] = 1; // 起点只有一种路径
// 遍历网格,计算每个位置的路径数量
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == 1) continue; // 如果当前位置是障碍物,跳过
// 从上方到达当前位置的路径数
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
// 从左方到达当前位置的路径数
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
// 输出到达终点的路径数量
System.out.println(dp[n - 1][m - 1]);
}
}
import java.util.Scanner;
public class Main {
static int n;
static int m;
static int[][] matrix;
static int[][] offsets = {{1, 0}, {0, 1}}; // 移动方向:下和右
static int ans = 0; // 记录路径数量
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt(); // 读取行数n
m = sc.nextInt(); // 读取列数m
matrix = new int[n][m]; // 创建网格矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = sc.nextInt(); // 读取每个位置的值
}
}
// 如果起点是可通行的,开始递归搜索
if (matrix[0][0] == 0) {
dfs(0, 0);
}
// 输出路径数量
System.out.println(ans);
}
public static void dfs(int x, int y) {
// 如果到达终点,增加路径数量
if (x == n - 1 && y == m - 1) {
ans++;
return;
}
// 遍历可能的移动方向
for (int[] offset : offsets) {
int newX = x + offset[0]; // 新的位置x
int newY = y + offset[1]; // 新的位置y
// 检查新位置是否越界,是否为障碍物
if (newX < 0 || newX >= n || newY < 0 || newY >= m || matrix[newX][newY] == 1) {
continue; // 如果不符合条件,跳过
}
// 递归访问新位置
dfs(newX, newY);
}
}
}
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
static int n;
static int m;
static int[][] matrix;
static int[][] offsets = {{1, 0}, {0, 1}}; // 移动方向:下和右
static int ans = 0; // 记录路径数量
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt(); // 读取行数n
m = sc.nextInt(); // 读取列数m
matrix = new int[n][m]; // 创建网格矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = sc.nextInt(); // 读取每个位置的值
}
}
// 如果起点是可通行的,开始栈式DFS
if (matrix[0][0] == 0) {
dfs();
}
// 输出路径数量
System.out.println(ans);
}
public static void dfs() {
LinkedList<Integer> stack = new LinkedList<>(); // 使用栈来模拟递归
// 将起点压入栈中,位置编码为x*m + y
stack.addLast(0 * m + 0);
while (!stack.isEmpty()) {
int pos = stack.removeLast(); // 取出栈顶位置
int x = pos / m; // 计算行号
int y = pos % m; // 计算列号
// 如果到达终点,增加路径数量
if (x == n - 1 && y == m - 1) {
ans++;
continue;
}
// 遍历可能的移动方向
for (int[] offset : offsets) {
int newX = x + offset[0]; // 新的位置x
int newY = y + offset[1]; // 新的位置y
// 检查新位置是否越界,是否为障碍物
if (newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX][newY] == 0) {
stack.addLast(newX * m + newY); // 将新位置压入栈中
}
}
}
}
}
matrix
中。dp
,dp[i][j]
表示从起点到位置(i,j)的路径数量。起点dp[0][0]
初始化为1。dp[n-1][m-1]
即为到达终点的路径数量。dfs
函数开始递归搜索。dfs
:
ans
。ans
。ans
。ans
。每个方法都有其优缺点,动态规划在时间和空间复杂度上更优,而DFS适用于路径数量较少的情况,或者需要记录具体路径的情况。
# 输入获取
n, m = map(int, input().split()) # 读取网格的长和宽,n表示行数,m表示列数
matrix = [list(map(int, input().split())) for _ in range(n)] # 读取网格矩阵,0表示可通行,1表示障碍物
# 算法入口
def getResult():
# 如果起点或终点是障碍物,则无法通过
if matrix[0][0] == 1 or matrix[n - 1][m - 1] == 1:
return 0
# 初始化动态规划二维数组,dp[i][j]表示从起点到达位置(i, j)的路径数量
dp = [[0 for _ in range(m)] for _ in range(n)]
dp[0][0] = 1 # 起点初始化为1,表示只有一种方式到达起点(即不移动)
# 遍历整个网格
for i in range(n):
for j in range(m):
# 如果当前位置是障碍物,跳过
if matrix[i][j] == 1:
continue
# 如果当前位置可以从上方到达,则累加上方的路径数量
if i > 0:
dp[i][j] += dp[i - 1][j]
# 如果当前位置可以从左方到达,则累加左方的路径数量
if j > 0:
dp[i][j] += dp[i][j - 1]
# 返回终点位置的路径数量
return dp[n - 1][m - 1]
# 算法调用
print(getResult())
0
表示可通行,1
表示障碍物。0
。dp
,其大小与网格大小一致。dp[0][0]
为1
,表示只有一种路径从起点到起点。dp[n-1][m-1]
的路径数量。# 输入获取
n, m = map(int, input().split()) # 读取网格的长和宽,n表示行数,m表示列数
matrix = [list(map(int, input().split())) for _ in range(n)] # 读取网格矩阵,0表示可通行,1表示障碍物
# 定义向下和向右移动的偏移量
offsets = ((1, 0), (0, 1))
# 用于记录可行路径数量
ans = 0
# 深度优先搜索递归函数
def dfs(x, y):
global ans # 使用全局变量来记录路径数量
# 如果到达终点,说明当前分支路径可行,路径数量加1
if x == n - 1 and y == m - 1:
ans += 1
return
# 遍历可能的移动方向(向下、向右)
for offsetX, offsetY in offsets:
newX = x + offsetX # 计算新位置的行号
newY = y + offsetY # 计算新位置的列号
# 判断新位置是否越界,以及是否是障碍物
if n > newX >= 0 and m > newY >= 0 and matrix[newX][newY] == 0:
dfs(newX, newY) # 如果新位置可行,递归调用
# 算法调用
if matrix[0][0] == 0: # 如果起点可通行,则开始深搜
dfs(0, 0) # 从起点(0, 0)开始递归
print(ans)
offsets
,存储向下移动和向右移动的偏移量。dfs
:
ans
加1
。ans
。# 输入获取
n, m = map(int, input().split()) # 读取网格的长和宽,n表示行数,m表示列数
matrix = [list(map(int, input().split())) for _ in range(n)] # 读取网格矩阵,0表示可通行,1表示障碍物
# 定义向下和向右移动的偏移量
offsets = ((1, 0), (0, 1))
# 用于记录可行路径数量
ans = 0
# 使用栈模拟深度优先搜索
def dfs():
global ans # 使用全局变量来记录路径数量
stack = [] # 用栈来存储搜索的路径
# 如果起点可通行,则将起点加入栈
if matrix[0][0] == 0:
stack.append(0) # 使用单个整数记录位置,编码方式为 x * m + y
# 当栈不为空时,继续处理
while len(stack) > 0:
pos = stack.pop() # 取出栈顶的位置
x = pos // m # 解码行号
y = pos % m # 解码列号
# 如果到达终点,说明路径可行,路径数量加1
if x == n - 1 and y == m - 1:
ans += 1
continue
# 遍历向下和向右的两种移动方向
for offsetX, offsetY in offsets:
newX = x + offsetX # 计算新位置的行号
newY = y + offsetY # 计算新位置的列号
# 如果新位置没有越界,也不是障碍物,则将新位置压入栈
if n > newX >= 0 and m > newY >= 0 and matrix[newX][newY] == 0:
stack.append(newX * m + newY) # 将新位置编码为整数后压入栈
# 算法调用
dfs() # 调用栈实现的深搜
print(ans)
ans
。方法 | 时间复杂度 | 空间复杂度 | 特点 |
---|---|---|---|
动态规划 | O(n * m) | O(n * m) | 高效,可快速计算路径数量 |
递归 DFS | O(2^(n+m)) | O(n + m) | 简单实现,但可能导致栈溢出 |
栈实现 DFS | O(2^(n+m)) | O(n + m) | 避免栈溢出,适用于中小规模问题 |
根据需求选择适合的算法,动态规划是最佳选择,而DFS适用于路径较少的小规模问题。
#include
#include
using namespace std;
int main() {
// 读取网格的行数(n)和列数(m)
int n, m;
cin >> n >> m;
// 地图矩阵,matrix[i][j]表示网格中第i行第j列的位置
vector<vector<int>> matrix(n, vector<int>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> matrix[i][j]; // 输入地图矩阵,0表示可通行,1表示障碍物
}
}
// 如果起点或终点是障碍物,直接输出0并结束程序
if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
cout << 0 << endl;
return 0;
}
// 动态规划表:dp[i][j]表示从起点到达位置(i, j)的路径数量
vector<vector<long>> dp(n, vector<long>(m, 0));
dp[0][0] = 1; // 初始化起点为1,表示只有一种方式到达起点
// 遍历地图矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == 1) continue; // 如果当前位置是障碍物,跳过
// 如果可以从上方到达当前位置,则累加上方的路径数量
if (i > 0) dp[i][j] += dp[i - 1][j];
// 如果可以从左方到达当前位置,则累加左方的路径数量
if (j > 0) dp[i][j] += dp[i][j - 1];
}
}
// 输出最终从起点到达终点的路径数量
cout << dp[n - 1][m - 1] << endl;
return 0;
}
#include
int main() {
// 读取网格的行数(n)和列数(m)
int n, m;
scanf("%d %d", &n, &m);
// 定义地图矩阵,0表示可通行,1表示障碍物
int matrix[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &matrix[i][j]); // 输入地图矩阵
}
}
// 如果起点或终点是障碍物,直接输出0并结束程序
if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
printf("0\n");
return 0;
}
// 动态规划表:dp[i][j]表示从起点到达位置(i, j)的路径数量
long dp[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
dp[i][j] = 0; // 初始化动态规划表
}
}
dp[0][0] = 1; // 初始化起点为1
// 遍历地图矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == 1) continue; // 如果当前位置是障碍物,跳过
// 如果可以从上方到达当前位置,则累加上方的路径数量
if (i > 0) dp[i][j] += dp[i - 1][j];
// 如果可以从左方到达当前位置,则累加左方的路径数量
if (j > 0) dp[i][j] += dp[i][j - 1];
}
}
// 输出最终从起点到达终点的路径数量
printf("%ld\n", dp[n - 1][m - 1]);
return 0;
}
#include
#include
using namespace std;
// 网格大小
int n, m;
// 地图矩阵
vector<vector<int>> matrix;
// 向下和向右的偏移量
int offsets[2][2] = {{1, 0}, {0, 1}};
// 记录路径数量
int ans = 0;
// 递归深搜函数
void dfs(int x, int y) {
// 如果到达终点,记录一条可行路径
if (x == n - 1 && y == m - 1) {
ans++;
return;
}
// 遍历移动方向(向下或向右)
for (int i = 0; i < 2; i++) {
int newX = x + offsets[i][0];
int newY = y + offsets[i][1];
// 如果新位置合法且可通行,继续深搜
if (newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX][newY] == 0) {
dfs(newX, newY);
}
}
}
int main() {
// 读取网格大小
cin >> n >> m;
matrix.resize(n, vector<int>(m));
// 读取地图矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> matrix[i][j];
}
}
// 如果起点可通行,则开始深搜
if (matrix[0][0] == 0) {
dfs(0, 0);
}
// 输出路径数量
cout << ans << endl;
return 0;
}
#include
#include
// 网格大小
int n, m;
// 地图矩阵
int *matrix;
// 向下和向右的偏移量
int offsets[2][2] = {{1, 0}, {0, 1}};
// 记录路径数量
int ans = 0;
// 递归深搜函数
void dfs(int x, int y) {
// 如果到达终点,记录一条可行路径
if (x == n - 1 && y == m - 1) {
ans++;
return;
}
// 遍历移动方向(向下或向右)
for (int i = 0; i < 2; i++) {
int newX = x + offsets[i][0];
int newY = y + offsets[i][1];
// 如果新位置合法且可通行,继续深搜
if (newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX * m + newY] == 0) {
dfs(newX, newY);
}
}
}
int main() {
// 读取网格大小
scanf("%d %d", &n, &m);
matrix = (int *)calloc(n * m, sizeof(int));
// 读取地图矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &matrix[i * m + j]);
}
}
// 如果起点可通行,则开始深搜
if (matrix[0] == 0) {
dfs(0, 0);
}
// 输出路径数量
printf("%d\n", ans);
free(matrix);
return 0;
}
#include
#include
#include
using namespace std;
// 网格大小
int n, m;
// 地图矩阵
vector<vector<int>> matrix;
// 向下和向右的偏移量
int offsets[2][2] = {{1, 0}, {0, 1}};
// 记录路径数量
int ans = 0;
void dfs() {
stack<int> s;
if (matrix[0][0] == 0) {
s.push(0); // 起点位置编码为0
}
while (!s.empty()) {
int pos = s.top();
s.pop();
int x = pos / m; // 行号
int y = pos % m; // 列号
// 如果到达终点,记录一条可行路径
if (x == n - 1 && y == m - 1) {
ans++;
continue;
}
// 遍历移动方向(向下或向右)
for (int i = 0; i < 2; i++) {
int newX = x + offsets[i][0];
int newY = y + offsets[i][1];
// 如果新位置合法且可通行,压入栈中
if (newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX][newY] == 0) {
s.push(newX * m + newY);
}
}
}
}
int main() {
cin >> n >> m;
matrix.resize(n, vector<int>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> matrix[i][j];
}
}
dfs();
cout << ans << endl;
return 0;
}
C语言代码实现和中文解释均与C++类似,但C++更适合现代编程风格,支持STL容器。
华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。
机试是进入技术面的第一关:
华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。
技术面试需要手撕代码:
技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。
入职后的可信考试:
入职华为后,还需要通过“可信考试”。可信考试分为三个等级:
2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:
关注历年真题:
适应新题目:
掌握常见算法:
华为OD考试通常涉及以下算法和数据结构:
保持编程规范:
官方参考:
加入刷题社区:
寻找系统性的教程:
刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。
本地编写代码
调整心态,保持冷静
输入输出完整性
快捷键使用
Ctrl+D
,复制、粘贴和撤销分别为 Ctrl+C
,Ctrl+V
,Ctrl+Z
,这些可以正常使用。Ctrl+S
,以免触发浏览器的保存功能。浏览器要求
交卷相关
时间和分数安排
考试环境准备
技术问题处理
祝你考试顺利,取得理想成绩!