给定一个m×n的网格,每个格子上包含一个非负整数。在网格上移动时,每次只能向下或者向右移动一步。请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 样列1: 输入:grid = [[1,3,1],[1,5,1],[4,2,1]] 输出:7 解释:因为路径 1→3→1→1→1 的总和最小。 样列2: 输入:grid = [[1,2,3],[4,5,6]] 输出:12 解释:因为路径 1→2→3→6 的总和最小。 1-2、请用分支限界法解决此问题,问题分析与算法原理,用java代码实现
时间: 2023-12-14 22:35:39 浏览: 38
问题分析:
这道题可以通过动态规划或分支限界法来解决。这里我们采用分支限界法。
首先,我们定义一个状态类(State),用于存储当前状态的信息。其中包括当前所在的行数(row)、列数(col)、已走过的路径长度(len)和路径上的数字总和(sum)。
接着,我们使用一个优先队列(priority queue)来存储所有的状态。队列中的状态按照路径上的数字总和从小到大排序,每次取出队首元素(即当前数字总和最小的状态),并扩展出其所有可行的子状态,并将这些子状态加入队列中。
当队列为空时,我们就找到了从左上角到右下角数字总和最小的路径。
算法原理:
1. 将起点状态加入队列中。
2. 当队列不为空时,取出队首元素(即当前数字总和最小的状态),并扩展出其所有可行的子状态,并将这些子状态加入队列中。
3. 对于每个子状态,计算其路径上的数字总和,并将其加入队列中。
4. 如果当前状态为终点状态,则更新最小数字总和,并终止搜索。
Java代码实现:
```java
import java.util.*;
public class Solution {
// 定义状态类
static class State implements Comparable<State> {
int row, col, len, sum;
public State(int row, int col, int len, int sum) {
this.row = row;
this.col = col;
this.len = len;
this.sum = sum;
}
// 重写 compareTo 方法,使状态按照数字总和从小到大排序
@Override
public int compareTo(State other) {
return Integer.compare(this.sum, other.sum);
}
}
public static int minPathSum(int[][] grid) {
int m = grid.length, n = grid[0].length;
boolean[][] visited = new boolean[m][n];
PriorityQueue<State> pq = new PriorityQueue<>();
pq.offer(new State(0, 0, 1, grid[0][0]));
while (!pq.isEmpty()) {
State curr = pq.poll();
visited[curr.row][curr.col] = true;
if (curr.row == m - 1 && curr.col == n - 1) {
return curr.sum;
}
if (curr.row + 1 < m && !visited[curr.row + 1][curr.col]) {
pq.offer(new State(curr.row + 1, curr.col, curr.len + 1, curr.sum + grid[curr.row + 1][curr.col]));
}
if (curr.col + 1 < n && !visited[curr.row][curr.col + 1]) {
pq.offer(new State(curr.row, curr.col + 1, curr.len + 1, curr.sum + grid[curr.row][curr.col + 1]));
}
}
return -1;
}
public static void main(String[] args) {
int[][] grid1 = {{1, 3, 1}, {1, 5, 1}, {4, 2, 1}};
System.out.println(minPathSum(grid1)); // expect 7
int[][] grid2 = {{1, 2, 3}, {4, 5, 6}};
System.out.println(minPathSum(grid2)); // expect 12
}
}
```