首页 > 试题广场 >

最大路径和

[编程题]最大路径和
  • 热度指数:853 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个矩阵matrix,先从左上角开始,每一步只能往右或者往下走,走到右下角。然后从右下角出发,每一步只能往上或者往左走,再回到左上角。任何一个位置的数字,只能获得一遍。返回最大路径和。


输入描述:
第一行输入两个整数M和N,M,N<=200
接下来M行,每行N个整数,表示矩阵中元素


输出描述:
输出一个整数,表示最大路径和
示例1

输入

5 10
1 1 1 1 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0
0 0 0 0 1 1 1 1 1 1

输出

16
示例2

输入

5 10
1 1 1 1 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 1
1 0 0 0 1 0 0 0 1 0
0 0 0 0 1 1 1 1 0 1

输出

15
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Code03_CherryPickup {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StreamTokenizer in = new StreamTokenizer(br);
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        while (in.nextToken() != StreamTokenizer.TT_EOF) {
            int N = (int) in.nval;
            in.nextToken();
            int M = (int) in.nval;
            int[][] matrix = new int[N][M];
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    in.nextToken();
                    matrix[i][j] = (int) in.nval;
                }
            }
            out.println(cherryPickup(matrix));
            out.flush();
        }
    }

    // 如下方法,在leetcode上提交也能通过
    // 测试链接 : https://leetcode.cn/problems/cherry-pickup/
    public static int cherryPickup(int[][] grid) {
        int N = grid.length;
        int M = grid[0].length;
        int[][][] dp = new int[N][M][N];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                for (int k = 0; k < N; k++) {
                    dp[i][j][k] = Integer.MIN_VALUE;
                }
            }
        }
        int ans = process(grid, 0, 0, 0, dp);
        return ans < 0 ? 0 : ans;
    }

    public static int process(int[][] grid, int x1, int y1, int x2, int[][][] dp) {
        if (x1 == grid.length || y1 == grid[0].length || x2 == grid.length || x1 + y1 - x2 == grid[0].length) {
            return Integer.MIN_VALUE;
        }
        if (dp[x1][y1][x2] != Integer.MIN_VALUE) {
            return dp[x1][y1][x2];
        }
        if (x1 == grid.length - 1 && y1 == grid[0].length - 1) {
            dp[x1][y1][x2] = grid[x1][y1];
            return dp[x1][y1][x2];
        }
        int next = Integer.MIN_VALUE;
        next = Math.max(next, process(grid, x1 + 1, y1, x2 + 1, dp));
        next = Math.max(next, process(grid, x1 + 1, y1, x2, dp));
        next = Math.max(next, process(grid, x1, y1 + 1, x2, dp));
        next = Math.max(next, process(grid, x1, y1 + 1, x2 + 1, dp));
        if (grid[x1][y1] == -1 || grid[x2][x1 + y1 - x2] == -1 || next == -1) {
            dp[x1][y1][x2] = -1;
            return dp[x1][y1][x2];
        }
        if (x1 == x2) {
            dp[x1][y1][x2] = grid[x1][y1] + next;
            return dp[x1][y1][x2];
        }
        dp[x1][y1][x2] = grid[x1][y1] + grid[x2][x1 + y1 - x2] + next;
        return dp[x1][y1][x2];
    }

}
发表于 2024-07-07 19:52:52 回复(0)
import java.util.Scanner;

public class Code03_CherryPickup {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        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();
            }
        }
        int ans = cherryPickup(matrix);
        System.out.println(ans);
        sc.close();
    }

    public static int cherryPickup(int[][] grid) {
        int N = grid.length;
        int M = grid[0].length;
        int[][][] dp = new int[N][M][N];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                for (int k = 0; k < N; k++) {
                    dp[i][j][k] = Integer.MIN_VALUE;
                }
            }
        }
        int ans = process(grid, 0, 0, 0, dp);
        return ans < 0 ? 0 : ans;
    }

    public static int process(int[][] grid, int x1, int y1, int x2, int[][][] dp) {
        if (x1 == grid.length || y1 == grid[0].length || x2 == grid.length || x1 + y1 - x2 == grid[0].length) {
            return Integer.MIN_VALUE;
        }
        if (dp[x1][y1][x2] != Integer.MIN_VALUE) {
            return dp[x1][y1][x2];
        }
        if (x1 == grid.length - 1 && y1 == grid[0].length - 1) {
            dp[x1][y1][x2] = grid[x1][y1];
            return dp[x1][y1][x2];
        }
        int next = Integer.MIN_VALUE;
        next = Math.max(next, process(grid, x1 + 1, y1, x2 + 1, dp));
        next = Math.max(next, process(grid, x1 + 1, y1, x2, dp));
        next = Math.max(next, process(grid, x1, y1 + 1, x2, dp));
        next = Math.max(next, process(grid, x1, y1 + 1, x2 + 1, dp));
        if (grid[x1][y1] == -1 || grid[x2][x1 + y1 - x2] == -1 || next == -1) {
            dp[x1][y1][x2] = -1;
            return dp[x1][y1][x2];
        }
        if (x1 == x2) {
            dp[x1][y1][x2] = grid[x1][y1] + next;
            return dp[x1][y1][x2];
        }
        dp[x1][y1][x2] = grid[x1][y1] + grid[x2][x1 + y1 - x2] + next;
        return dp[x1][y1][x2];
    }
发表于 2022-11-05 19:42:06 回复(0)
import java.util.*;

public class Main {
    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
        int row = sc.nextInt();
        int col = sc.nextInt();
        int[][] matrix = new int[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                matrix[i][j] = sc.nextInt();
            }
        }
        System.out.println(cherryPick(matrix));
    }
    
	//解题思路:让两个小人从左上走到右下,两人都只能往右或往下走,因此其中一条就表示去时的路,
	//而另一条表示回来时的路。因此当两人一旦相遇时,若该位置有樱桃,则记录为只拿了一次樱桃,否则
	//则记录为拿了两次樱桃。运用递归找到最大拿取樱桃的数量
	public static int cherryPick(int[][] m) {
		if (m == null || m[0] == null)
			return 0;
		int N = m.length;
		int M = m[0].length;
		if (N == 0 || M == 0)
			return 0;
		int[][][] dp = new int[N][M][N];
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				for (int k = 0; k < N; k++) {
					dp[i][j][k] = -1;
				}
			}
		}
		return process(m, N, M, 0, 0, 0, dp);
	}
	
	
	//注意表示两小人坐标时,之所有没有y2是因为x1 + y1 == x2 + y2, 因此y2 = x1 + y1 - x2!
	//此函是表示两小人从(x1, y1)与(x2, y2)位置出发,走到右下角的情况下,能获得的最大樱桃数是多少
	//dp[x1][y1][x2] == -1: 要么还没算过当前结果,要么已经算过了是无效解,总之都不能直接用
	public static int process(int[][] m, int N, int M, int x1, int y1, int x2, int[][][] dp) {
		//越界了返回无效值
		if (x1 == N || x2 == N || y1 == M || (x1 + y1 - x2) == M)
			return -1;
		if (dp[x1][y1][x2] != -1)
			return dp[x1][y1][x2];
		//当两人同时走到右下角
		if (x1 == N-1 && x2 == x1) {
			dp[x1][y1][x2] = m[N-1][M-1];
			return m[N-1][M-1];
		}
		//找接下来能获得的最大樱桃数
		int next = -1;
		//1号小人往下走,2号小人往右走
		next = Math.max(process(m, N, M, x1 + 1, y1, x2, dp), next);
		//1号小人往下走,2号小人往下走
		next = Math.max(process(m, N, M, x1 + 1, y1, x2 + 1, dp), next);
		//1号小人往右走,2号小人往右走
		next = Math.max(process(m, N, M, x1, y1 + 1, x2, dp), next);
		//1号小人往右走,2号小人往右走
		next = Math.max(process(m, N, M, x1, y1 + 1, x2 + 1, dp), next);
		//如果下面干脆走不通,返回无效解
		if (next == -1)
			return -1;
		//两人相遇时
		if (x1 == x2) {
			dp[x1][y1][x2] = m[x1][y1] + next;
		}
		else {
			dp[x1][y1][x2] = m[x1][y1] + m[x2][x1+y1-x2] + next;
		}
		return dp[x1][y1][x2];
	}
}


发表于 2022-04-02 18:14:25 回复(0)

问题信息

上传者:小小
难度:
3条回答 2891浏览

热门推荐

通过挑战的用户

最大路径和