898. 数字三角形 - AcWing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = 520;
int INF = (int)1e9;
int[][] a = new int[N][N];
int[][] f = new int[N][N];
int n = sc.nextInt();
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= i; j ++){
a[i][j] = sc.nextInt();
}
}
for(int i = 0; i <= n; i ++){
Arrays.fill(f[i], -INF);
}
f[1][1] = a[1][1];
for(int i = 2; i <= n; i ++){
for(int j = 1; j <= i; j ++){
f[i][j] = Math.max(f[i - 1][j - 1] + a[i][j], f[i - 1][j] + a[i][j]);
}
}
int res = -INF;
for(int i = 1; i <= n; i ++){
res = Math.max(res, f[n][i]);
}
System.out.print(res);
}
}
1015. 摘花生 - AcWing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while(n -- > 0){
int r = sc.nextInt();
int c = sc.nextInt();
int N = 110;
int INF = (int)1e9;
int[][] a = new int[N][N];
int[][] f = new int[N][N];
for(int i = 1; i <= r; i ++){
for(int j = 1; j <= c; j ++){
a[i][j] = sc.nextInt();
}
}
//这里和数字三角形模型不同的是数组f不用赋为无穷小
f[1][1] = a[1][1];
for(int i = 1; i <= r; i ++){
for(int j = 1; j <= c; j ++){
//只能由左往右,由上往下
f[i][j] = Math.max(f[i - 1][j] + a[i][j], f[i][j - 1] + a[i][j]);
}
}
System.out.println(f[r][c]);
}
}
}
1018. 最低通行费 - AcWing题库
由于题目限制了商人必须在2n - 1的时间内走出去,也就是不走回头路,就是说只能往右走或者往下走,其实本质上和摘花生这个题是一样的。
然后再考虑一下边界情况就可以了。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int N = 110;
int INF = (int)1e8;
int[][] a = new int[N][N];
int[][] f = new int[N][N];
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
a[i][j] = sc.nextInt();
}
}
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
if(i == 1 && j == 1){
f[i][j] = a[i][j];
}else{
f[i][j] = INF;//因为要和自己比最小,所以一开始要赋值为最大
//如果i=1,那么就是只能是由左往右来走,执行第二条语句
//如果j=1,那么就是只能由上往下来走,执行第一条语句
//这里与摘花生不同的是要判断边界情况,然后把dp语句细化
//只有不在第一行的时候才可以从上面过来
if(i > 1) f[i][j] = Math.min(f[i][j], f[i - 1][j] + a[i][j]);
//只有不在第一列的时候才可以从左边过来
if(j > 1) f[i][j] = Math.min(f[i][j], f[i][j - 1] + a[i][j]);
}
}
}
System.out.print(f[n][n]);
}
}
1027. 方格取数 - AcWing题库
只有在步数一样的时候才有可能踩到相同的格子。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = 15;
int[][] w = new int[N][N];
int[][][] f = new int[2 * N][N][N];
int n = sc.nextInt();
while(true){
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
if(a == 0 && b == 0 && c == 0) break;
w[a][b] = c;
}
for(int k = 2; k <= n + n; k ++){
for(int i1 = 1; i1 <= n; i1 ++){
for(int i2 = 1; i2 <= n; i2 ++){
int j1 = k - i1;
int j2 = k - i2;
if(j1 >= 1 && j2 >= 1 && j2 <= n && j1 <= n){
int t = w[i1][j1];//如果重叠的话,就只加任意一个
if(j1 != j2) t += w[i2][j2];//否则两个点都加上
//分别代表四种可能的情况
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1 - 1][i2] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1][i2] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1 - 1][i2 - 1] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1][i2 - 1] + t);
}
}
}
}
System.out.print(f[2 * n][n][n]);
}
}
275. 传纸条 - AcWing题库
题目本质上和方格取数是一样的,只是矩阵不一样。
题目中要求从左上到右下,和右下到左上,其实都可以看作是
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int N = 60;
int[][] w = new int[N][N];
int[][][] f = new int[2 * N][N][N];
//题目本质上和方格取数是一样的,只是一个是n×n矩阵,一个是m×n矩阵
for(int i = 1; i <= m; i ++){
for(int j = 1; j <= n; j ++){
w[i][j] = sc.nextInt();
}
}
for(int k = 2; k <= n + m; k ++){
for(int i1 = 1; i1 <= m; i1 ++){
for(int i2 = 1; i2 <= m; i2 ++){
int j1 = k - i1;
int j2 = k - i2;
if(j1 >= 1 && j2 >= 1 && j2 <= n && j1 <= n){
int t = w[i1][j1];
if(i1 != i2) t += w[i2][j2];
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1 - 1][i2] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1][i2] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1 - 1][i2 - 1] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1][i2 - 1] + t);
}
}
}
}
System.out.print(f[m + n][m][m]);
}
}