第一行输入两个整数 n 和 m,表示矩阵的大小。
接下来 n 行每行 m 个整数表示矩阵。
输出一个整数表示答案。
4 4 1 3 5 9 8 1 3 4 5 0 6 1 8 8 4 0
12
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().split(" "); int n = Integer.parseInt(params[0]), m = Integer.parseInt(params[1]); int[][] grid = new int[n][m]; for(int i = 0; i < n; i++){ params = br.readLine().split(" "); for(int j = 0; j < m; j++) grid[i][j] = Integer.parseInt(params[j]); } for(int i = 1; i < m; i++) grid[0][i] += grid[0][i - 1]; for(int i = 1; i < n; i++) grid[i][0] += grid[i - 1][0]; for(int i = 1; i < n; i++){ for(int j = 1; j < m; j++) grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]); } System.out.println(grid[n - 1][m - 1]); } }
import java.util.Scanner; public class Main{ public static int minPathSum(int[][] grid) { int[][] dp = new int[grid.length][grid[0].length]; dp[0][0] = grid[0][0]; //起点位置 //求第1列的值 for(int i = 1;i<grid.length;i++){ dp[i][0] = dp[i-1][0] + grid[i][0]; } //求第1行的值 for(int i = 1;i<grid[0].length;i++){ dp[0][i] = dp[0][i-1] + grid[0][i]; } //循环结束,最后的结果即为最小值 for(int i = 1;i<grid.length;i++){ for(int j = 1;j<grid[0].length;j++){ dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j]; } } return dp[grid.length-1][grid[0].length-1]; } public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int[][] arr = new int[n][m]; for(int i=0;i<n;i++){ for(int j = 0;j<m;j++){ arr[i][j] = sc.nextInt(); } } System.out.println(minPathSum(arr)); } }
#include<stdio.h> (737)#include<stdlib.h> int main() { int n, m; scanf("%d%d", &n, &m); int** a = (int**)malloc(sizeof(int*) * n); int** dp = (int**)malloc(sizeof(int*) * n); // for (int i = 0; i <= n - 1; i++) { a[i] = (int*)malloc(sizeof(int) * m); dp[i] = (int*)malloc(sizeof(int) * m); } // for (int i = 0; i <= n-1; i++) { for (int j = 0; j <= m-1; j++) { scanf("%d", &a[i][j]); } } //// for (int i = 0; i <= n; i++) { for (int j = 0; j <= m; j++) { if (i == 0 && j == 0) dp[i][j] = a[i][j]; else if (i == 0) dp[i][j] = dp[i][j - 1] + a[i][j]; else if (j == 0) dp[i][j] = dp[i - 1][j] + a[i][j]; else dp[i][j]= min(dp[i - 1][j], dp[i][j - 1]) + a[i][j]; } } // printf("%d", dp[n - 1][m - 1]); return 0; }
#include <vector> #include <iostream> #include <algorithm> using namespace std; int minPathSum1(const vector<vector<int>>& vec) { int row=vec.size(); int col=vec[0].size(); if(vec.empty()||row==0||col==0)return 0; vector<vector<int>> dp(row,vector<int>(col,0)); dp[0][0]=vec[0][0]; for(int i=1;i<row;++i)dp[i][0]=dp[i-1][0]+vec[i][0]; for(int j=1;j<col;++j)dp[0][j]=dp[0][j-1]+vec[0][j]; for(int i=1;i<row;++i) { for(int j=1;j<col;++j) { dp[i][j]=min(dp[i-1][j],dp[i][j-1])+vec[i][j]; } } return dp[row-1][col-1]; } int main() { int n,m; cin>>n>>m; vector<vector<int>>arr; int val; for(int i=0;i<n;++i) { vector<int> var; for(int j=0;j<m;++j) { cin>>val; var.push_back(val); } arr.push_back(var); } int res=minPathSum1(arr); cout<<res<<endl; return 0; }
int minPathSum2(const vector<vector<int>>& vec) { int row=vec.size(); int col=vec[0].size(); if(vec.empty()||row==0||col==0)return 0; int more,less; bool rowmore=false; if(row>col) { rowmore=true; more=row,less=col; }else{ more=col,less=row; } vector<int> arr(less,0);//辅助数组为行数与列数中最小值 arr[0]=vec[0][0]; for(int i=1;i<less;++i) { arr[i]=arr[i-1]+(rowmore?vec[0][i]:vec[i][0]); } for(int i=1;i<more;++i) { arr[0]=arr[0]+(rowmore?vec[i][0]:vec[0][i]); for(int j=1;j<less;++j){ arr[j]=min(arr[j-1],arr[j])+(rowmore?vec[i][j]:vec[j][i]); } } return arr[less-1]; }
#include <bits/stdc++.h> using namespace std; int main(){ int n, m; cin>>n>>m; int a[n][m]; for(int i=0;i<n;i++) for(int j=0;j<m;j++) cin>>a[i][j]; for(int i=1;i<m;i++) a[0][i] += a[0][i-1]; for(int i=1;i<n;i++) a[i][0] += a[i-1][0]; for(int i=1;i<n;i++) for(int j=1;j<m;j++) a[i][j] += min(a[i-1][j], a[i][j-1]); cout<<a[n-1][m-1]<<endl; return 0; }
#include <bits/stdc++.h> using namespace std; int main() { std::ios::sync_with_stdio(false); int n, m; cin >> n >> m; vector<vector<int>> A(n, vector<int>(m, 0)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> A[i][j]; } } vector<int> dp(A[0]); for (int j = 1; j < m; j++) { dp[j] += dp[j - 1]; } for (int i = 1; i < n; i++) { dp[0] = dp[0] + A[i][0]; for (int j = 1;j < m; j++) { dp[j] = min(dp[j - 1], dp[j]) + A[i][j]; } } cout << dp.back() << endl; return 0; }
import java.util.Scanner; public class Main { 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 result = minPathSum(matrix); System.out.println(result); } public static int minPathSum(int[][] m) { int row = m.length, col = m[0].length; int[][] dp = new int[row][col]; dp[0][0] = m[0][0]; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (i == 0 && j == 0) { continue; } if (i == 0) { dp[i][j] = m[i][j] + dp[i][j - 1]; } else if (j == 0) { dp[i][j] = m[i][j] + dp[i - 1][j]; } else { dp[i][j] = m[i][j] + Math.min(dp[i][j - 1], dp[i - 1][j]); } } } return dp[row - 1][col - 1]; } }
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner scanner = new Scanner(System.in); while(scanner.hasNext()){ int n = scanner.nextInt(); int m = scanner.nextInt(); int[][] value = new int[n][m]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ value[i][j] = scanner.nextInt(); } } System.out.println(minSum(value, n, m)); } } public static int minSum(int[][] value, int n, int m){ // 表示第i行j列的最小路径和 int[][] min = new int[n][m]; min[0][0] = value[0][0]; for(int i=1;i<n;i++){ min[i][0] = min[i-1][0] + value[i][0]; } for(int i=1;i<m;i++){ min[0][i] = min[0][i-1] + value[0][i]; } for(int i=1;i<n;i++){ for(int j=1;j<m;j++){ min[i][j] = Math.min(min[i-1][j], min[i][j-1]) + value[i][j]; } } return min[n-1][m-1]; } }
import java.util.*; public class Main1{ static int findMin(int[][] path,int row,int col) { if(row<1||col<1) return -1; else if(row==1&&col==1) return path[0][0]; else if(row==1) { int min=0; for(int i=0;i<col;i++) { min+=path[0][i]; } return min; } else if(col==1) { int min=0; for(int i=0;i<row;i++) { min+=path[i][0]; } return min; } int[][] dp=new int[row][col]; dp[0][0]=path[0][0]; for(int i=1;i<row;i++) { dp[i][0]=dp[i-1][0]+path[i][0]; } for(int i=1;i<col;i++) { dp[0][i]=dp[0][i-1]+path[0][i]; } for(int i=1;i<row;i++) { for(int j=1;j<col;j++) { dp[i][j]=Math.min(dp[i-1][j], dp[i][j-1])+path[i][j]; } } return dp[row-1][col-1]; } public static void main(String[] args){ int row;int col; Scanner in=new Scanner(System.in); while(in.hasNext()){ row=in.nextInt(); col=in.nextInt(); int[][] path=new int[row][col]; for(int i=0;i<row;i++) { for(int j=0;j<col;j++) { path[i][j]=in.nextInt(); } } System.out.println(findMin(path,row,col)); } } }
#include <vector> #include <iostream> #include <cstdio> using namespace std; /** * 读数据 * @param n 行数 * @param m 列数 * @param matrix 数组 * @return 空 */ void read_data(int &n, int &m, vector<vector<int>> &matrix) { cin >> n >> m; for (int i = 0; i < n; i++) { vector<int> vec_temp; for (int j = 0; j < m ; j++) { int element; scanf("%d", &element); vec_temp.push_back(element); } matrix.push_back(vec_temp); } return; } /** * 求最小路径和 * @param n 行数 * @param m 列数 * @param matrix n*m数组 * @return 最小路径和 */ int min_path(int n, int m, vector<vector<int>> &matrix) { // 记录行走距离的矩阵 vector<vector<int>> move_distance_matrix; move_distance_matrix.resize(n); for (int i = 0; i < n; ++i) { move_distance_matrix[i].resize(m); } for (int j = 0; j < n; ++j) { for (int k = 0; k < m; k++) { if (j == 0 && k == 0) { move_distance_matrix[j][k] = matrix[j][k]; } else if (j == 0) { move_distance_matrix[j][k] = move_distance_matrix[j][k - 1] + matrix[j][k]; } else if (k == 0) { move_distance_matrix[j][k] = move_distance_matrix[j - 1][k] + matrix[j][k]; } else { int right = move_distance_matrix[j][k - 1] + matrix[j][k]; int down = move_distance_matrix[j - 1][k] + matrix[j][k]; move_distance_matrix[j][k] = right > down ? down : right; } } } return move_distance_matrix[n - 1][m - 1]; } int main() { int n; int m; vector<vector<int>> matrix; read_data(n, m, matrix); cout << min_path(n, m, matrix); }
//参考别人的 #include<stdio.h> int main() { int i, j, n, m; scanf("%d %d", &n, &m); int a[10][10]; for (i = 0; i < n; i++) for (j = 0; j < m; j++) scanf("%d", &a[i][j]); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { if (i == 0 && j == 0) a[i][j] = 1; else { if (i == 0 && j != 0) a[i][j] += a[i][j - 1]; else { if (j == 0 && i != 0) a[i][j] += a[i - 1][j]; else { if (a[i - 1][j] < a[i][j - 1]) a[i][j] += a[i - 1][j]; else a[i][j] += a[i][j - 1]; } } } } } printf("%d", a[n - 1][m - 1]); return 0; }
根据LeetCode 64的思路写的,从右下角开始反着求
#include<iostream> #include<vector> using namespace std; int min_path_length(vector<vector<int> >matrix) { int row=matrix.size(),col=matrix[0].size(); const int j=row; const int k=col; int dp[j][k]; for(int i=row-1;i>=0;i--) { for(int j=col-1;j>=0;j--) { if(i==row-1 && j!=col-1) { dp[i][j]=matrix[i][j]+dp[i][j+1]; } else if(i!=row-1 && j==col-1) { dp[i][j]=matrix[i][j]+dp[i+1][j]; } else if(i!=row-1 && j!=col-1) { dp[i][j]=matrix[i][j]+min(dp[i+1][j],dp[i][j+1]); } else { dp[i][j]=matrix[i][j]; } } } return dp[0][0]; } int main() { vector<vector<int> >a; int n,m; while(cin>>n>>m) { for(int i=0;i<n;i++) { vector<int>temp; for(int j=0;j<m;j++) { int tmp; cin>>tmp; temp.push_back(tmp); } a.push_back(temp); } cout<<min_path_length(a)<<endl; } return 0; }
/* 运行时间:953ms 占用内存:43092k */ #include <iostream> #include <vector> using std::vector; using std::cin; using std::cout; using std::endl; class solution { private: int n,m; vector<int> map; // 将二维数组一维化 public: solution(/* args */); solution(int n, int m, vector<int> & map):map(map),n(n),m(m) {} void output(); int find_min(); void init(); // 计算左、下边界上的最短路径 ~solution(); }; inline int min(int a, int b); solution::solution(/* args */){ } solution::~solution() { } int solution::find_min() { init(); // 从左下向上依次更新(0,0)到该节点的最短路径 for (size_t i = 1; i < n; i++) { for (size_t j = 1; j < m; j++) { map[i*m+j] += min(map[(i-1)*m+j], map[i*m+j-1]); } } return map[n*m-1]; } void solution::output() { cout << find_min() << endl; } inline int min(int a, int b) { return a<=b?a:b; } void solution::init() { for (size_t i = 1; i < m; i++) { map[i] += map[i-1]; } for (size_t i = 1; i < n; i++) { map[i*m] += map[(i-1)*m]; } } void input(int &n, int &m, vector<int> & map) { cin >> n >> m; map.resize(n*m); for (size_t i = 0; i < n; i++) { for (size_t j = 0; j < m; j++) { cin >> map[i*m+j]; } } } int main(int argc, char* argv[]) { int n,m; vector<int> map; input(n, m, map); solution s(n, m, map); s.output(); return 0; }
常规的动态规划
#include <iostream> #include <vector> #include <algorithm> #include <limits.h> using namespace std; int main(){ int m, n; cin >> m >> n; vector<vector<int>> matrix(m, vector<int>(n, 0)); for (int i = 0; i < m; i++){ for (int j = 0; j < n; j++){ cin >> matrix[i][j]; } } vector<vector<int>> sum_matrix(m + 1, vector<int>(n + 1, INT_MAX)); sum_matrix[1][1] = matrix[0][0]; for (int i = 0; i < m; i++){ for (int j = 0; j < n; j++){ if (i == 0 && j == 0) continue; int idx = i + 1; int idy = j + 1; sum_matrix[idx][idy] = matrix[i][j] + min(sum_matrix[idx - 1][idy], sum_matrix[idx][idy - 1]); } } cout << sum_matrix[m][n] << endl; return 0; }
def shortestRoadSum(arr, n, m): #生成n行m列的0矩阵dp dp = [[0 for i in range(m)] for j in range(n)] dp[0][0] = arr[0][0] for i in range(1, n): #第一列只能由上向下走 dp[i][0] = dp[i-1][0] + arr[i][0] for j in range(1, m): #第一行只能由左向右走 dp[0][j] = dp[0][j-1] + arr[0][j] for i in range(1, n): for j in range(1, m): dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + arr[i][j] return dp[n-1][m-1] n, m = map(int, input().split()) #输入二维矩阵 arr = [] for i in range(n): arr.append(list(map(int, input().split()))) print(shortestRoadSum(arr, n, m))
def shortestPathSum(arr, n, m): #直接修改arr for i in range(1, n): #第一列只能由上向下走 arr[i][0] = arr[i-1][0] + arr[i][0] for j in range(1, m): #第一行只能由左向右走 arr[0][j] = arr[0][j-1] + arr[0][j] for i in range(1, n): for j in range(1, m): arr[i][j] = min(arr[i-1][j], arr[i][j-1]) + arr[i][j] return arr[n-1][m-1] n, m = map(int, input().split()) arr = [] for i in range(n): arr.append(list(map(int, input().split()))) print(shortestPathSum(arr, n, m))牛客的是否ac可能和网速和服务器有关,不稳定,同时python与其他语言比起来,运行时间确实算长的,毕竟是解释型语言,感觉每次都走在超时的边缘
def shortestRoadSum(arr, n, m): # 每次只保留一行结果 dp = arr[0] # 更新第一行的结果 for j in range(1, m): # 第一行只能由左向右走 dp[j] += dp[j - 1] for i in range(1, n): dp[0] += arr[i][0] #每一行开始遍历时更新第一个元素 for j in range(1, m): dp[j] = min(dp[j-1],dp[j]) + arr[i][j] return dp[-1] n, m = map(int, input().split()) # 输入二维矩阵 arr = [] for i in range(n): arr.append(list(map(int, input().split()))) print(shortestRoadSum(arr, n, m))使用一维矩阵来保存每一行的最优结果,想明白的感觉真好
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int[][] nums = new int[n][m]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ nums[i][j] = sc.nextInt(); } } int[][] dp = new int[n][m]; dp[0][0] = nums[0][0]; for(int i=1;i<n;i++){ dp[i][0] = nums[i][0] + dp[i-1][0]; } for(int i=1;i<m;i++){ dp[0][i] = nums[0][i] + dp[0][i-1]; } for(int i=1;i<n;i++){ for(int j=1;j<m;j++){ dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1]) + nums[i][j]; } } System.out.println(dp[n-1][m-1]); } }