Skip to content

Latest commit

 

History

History
275 lines (247 loc) · 7.27 KB

0036.网格路径和.md

File metadata and controls

275 lines (247 loc) · 7.27 KB

36. 网格路径和

题目链接

C++

// 解法一: 动态规划
// 思路:
// 先根据输入数据构造图
// dfs遍历图,穷举所有可能路径
// 输出路径中的最大值
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;

string s;

// 读入数据
void input(vector<vector<int>>& grid) {
    int pos = 1;
    while(pos < s.size() - 1) {
        if(s[pos] == '[') {
            vector<int> path;
            int num = 0;
            pos++;
            while(s[pos] != ']') {
                num = num * 10 + (int)(s[pos] - 48);
                pos++;
                if(s[pos] == ',') {
                    path.push_back(num);
                    num = 0;
                    pos++;
                }
            }
            path.push_back(num);
            num = 0;
            pos++;
            grid.push_back(path);
        }
        pos++;
    }
}

void solve() {
    vector<vector<int>> grid; // 存储网格图
    input(grid);
    int n = grid.size();
    int m = grid[0].size();
    // dp[i][j]的意思是到达grid[i][j]时的路径最大和
    vector<vector<int>> dp(n, vector<int>(m, 0));
    
    // 初始化
    dp[0][0] = grid[0][0];
    for(int i = 1; i < n; ++i) {
        dp[i][0] = dp[i - 1][0] + grid[i][0];
    }
    for(int i = 1; i < m; ++i) {
        dp[0][i] = dp[0][i - 1] + grid[0][i];
    }
    
    // 遍历图,由于每次只能向下或者向右移动一格
    // 所以dp[i][j]来自上方或者左侧
    // 取两者的最大值 + grid[i][j]就是dp[i][j]的值
    for(int i = 1; i < n; ++i) {
        for(int j = 1; j < m; ++j) {
            dp[i][j] = max(dp[i - 1][j] + grid[i][j], dp[i][j - 1] + grid[i][j]);
        }
    }
    
    cout << dp[n - 1][m - 1] << endl;
}


int main()
{
    while(cin >> s) {
        solve();
    }
    return 0;
}
// 解法二: (因为要找到所有路径,速度比解法一慢很多)
// 思路:
// 先根据输入数据构造图
// dfs遍历图,穷举所有可能路径
// 输出路径中的最大值
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;

string s;

int dir[2][2] = {1, 0, 0, 1}; // 存储方向
int ans = 0; // 存储答案
int n, m; 

void dfs(vector<vector<int>>& grid, int x, int y, int sum) {
    // 如果走到了右下角,取答案最大值
    if(x == n - 1 && y == m - 1) {
        ans = max(ans, sum);
        return;
    }
    // 遍历两个方向
    for(int i = 0; i < 2; ++i) {
        int nx = x + dir[i][0];
        int ny = y + dir[i][1];
        // 如果越界则跳过
        if(nx < 0 || nx >= n || ny < 0 || ny >= m) {
            continue;
        }
        //回溯
        sum += grid[nx][ny];
        dfs(grid, nx, ny, sum);
        sum -= grid[nx][ny];
    }
    return;
}

void solve() {
    vector<vector<int>> grid; // 存储网格图
    int pos = 1;
    // 读入数据
    while(pos < s.size() - 1) {
        if(s[pos] == '[') {
            vector<int> path;
            int num = 0;
            pos++;
            while(s[pos] != ']') {
                num = num * 10 + (int)(s[pos] - 48);
                pos++;
                if(s[pos] == ',') {
                    path.push_back(num);
                    num = 0;
                    pos++;
                }
            }
            path.push_back(num);
            num = 0;
            pos++;
            grid.push_back(path);
        }
        pos++;
    }
    n = grid.size();
    m = grid[0].size();
    // dfs找到所有路径中的最大值
    dfs(grid, 0, 0, grid[0][0]);
    cout << ans << endl;
}


int main()
{
    while(cin >> s) {
        solve();
    }
    return 0;
}

Java

/**
 * 思路:动态规划
 * 当解决网格中的路径问题的时候,我们需要考虑如何在每
 * 个格子上做出最优的选择,以确保获取最大的路径和。
 * 
 * 对于这个问题,通过创建一个和网格一样大小的二维数组 dp,
 * 其中,dp[i][j]代表了从左上角到达格子(i, j)位置的
 * 最大路径和。
 * 
 * 其次,对二维数组的第一行和第一列进行初始化,因为
 * 这两个方向上只有一种移动方式,即一直向右或一直向下。
 * 不受其他方向的影响。
 * 
 * 接下来,从第二行、第二列开始,逐步填充数组 dp,对于
 * 位置(i, j),我们可以从该位置的上方(i - 1, j)和
 * 该位置的左方(i, j - 1)移动到当前位置。只需要选择
 * 这两个方向中较大的那个路径和,就可到达当前位置的最大路径和。
 */
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String arrayString = scanner.next();
        int[][] grid = parse2dArray(arrayString);
        System.out.println(maxPathSum(grid));
    }
    public static int maxPathSum(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 i = 1; i < m; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][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++) {
            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 int[][] parse2dArray(String arrayString) {
        String[] rowStrings = arrayString.substring(2, arrayString.length() - 2).split("],");
        // "[[1,2,3],[2,3,4],[3,4,5]]" -> "[1,2,3", "[2,3,4", "[3,4,5]"
        int rows = rowStrings.length;
        int cols = rowStrings[0].split(",").length;
        int[][] digital2dArray = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            String rowString = rowStrings[i].replaceAll("\\[|\\]", ""); // 去除所有中括号
            // "[1,2,3" -> "1,2,3"
            // "[2,3,4" -> "2,3,4"
            // "[3,4,5]" -> "3,4,5"
            String[] elements = rowString.split(",");
            // "1,2,3" -> 1 2 3
            // "2,3,4" -> 2 3 4
            // "3,4,5" -> 3 4 5
            for (int j = 0; j < cols; j++) {
                digital2dArray[i][j] = Integer.parseInt(elements[j]);
            }
        }
        return digital2dArray;
    }
}

Python

# 现有一个 m * n的网格,每个网格上都有一个非零整数,每次只能向下或者向右移动一格,计算从左上开始移动到右下的所有路径上数字的最大和。
# 输入:[[2,3,1],[2,5,3],[4,2,1]] 输出:14
# 使用动态规划,与java思路相同

def dp(nums):
    m = len(nums)
    n = len(nums[0])
    if m == 0 or n == 0:
        return 0
    dp = [[0 for _ in range(n)] for _ in range(m)]
    dp[0][0] = nums[0][0]
    for i in range(1, m):
        dp[i][0] = nums[i][0] + dp[i-1][0]
    for i in range(1, n):
        dp[0][i] = nums[0][i] + dp[0][i-1]
    for i in range(1, m):
        for k in range(1, n):
            dp[i][k] = max(dp[i-1][k], dp[i][k-1]) + nums[i][k]
    return dp[m-1][n-1]
    pass
s = input()
nums = eval(s)
print(dp(nums=nums))

Go

JS

C