金币路径问题及其解法
在算法与编程中,“金币路径”问题是一个经典的动态规划示例。这个问题通常涉及到在一个二维网格中收集金币,同时限制了移动的方向。本文将对此问题进行详细探讨,并提供 Java 的代码示例,帮助读者更好地理解这一主题。
问题描述
假设你位于一个 m x n 的网格中,网格的每个单元格中都有金币,任务是找到一条路径,使得你经过的单元格中的金币总数最大。你只能向下或向右移动。
示例
假设有如下网格:
| 1 | 2 | ||
|---|---|---|---|
| 3 | 1 | ||
| 1 | 2 | 4 | |
| 2 | 1 | 5 |
从 (0,0) 移动到 (2,2) 的最大金币数是 12,路径为 (0,0) -> (0,1) -> (1,1) -> (1,2) -> (2,2)。
解法思路
采用动态规划的方式,我们可以构建一个 dp 数组,其中 dp[i][j] 表示到达 (i,j) 位置时获得的最高金币数。转移方程如下:
- 如果当前单元格有金币,则
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + grid[i][j] - 边界情况:如果
i或j为0,则我们只能从一个方向移动到达该点。
代码示例
下面是实现上述逻辑的 Java 代码示例:
public class CoinPath {
public int maxCoins(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
// 初始化起点
dp[0][0] = grid[0][0];
// 填充第一行
for (int j = 1; j < n; j++) {
dp[0][j] = dp[0][j - 1] + grid[0][j];
}
// 填充第一列
for (int i = 1; i < m; i++) {
dp[i][0] = dp[i - 1][0] + grid[i][0];
}
// 填充其余部分
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[m - 1][n - 1];
}
public static void main(String[] args) {
CoinPath cp = new CoinPath();
int[][] grid = {
{0, 3, 1},
{2, 0, 4},
{1, 5, 0}
};
System.out.println("最大金币数: " + cp.maxCoins(grid));
}
}
图示化旅行路径
在理解了动态规划算法后,我们可以运用 Mermaid 来可视化路径:
journey
title 金币路径旅行
section 开始
开始: 0: 0
section 移动
向右到 (0, 1): 2: 0
向下到 (1, 1): 3: 0
向右到 (1, 2): 4: 0
向下到 (2, 2): 5: 0
总结
在“金币路径”问题中,利用动态规划的方式不仅高效解决了问题,也为我们解决其他类似问题提供了深刻的思考方法。通过上述 Java 代码和路径可视化,希望读者对这一经典问题有了更深入的理解,并能灵活运用至其他编程实践中。面对更复杂的应用场景,我们也可以根据情况进行扩展与优化。
















