前言:用惯了傻瓜式dfs 做什么题都直接用暴力破解然后终于有一天扑街了 ac不过 时间严重爆表 然后开始了dp之路 下面开始我的小案例。四个角度递推 Working out 。
话不多说直接上题。
题目:
给n*m的矩阵,每个格子有个数,A从(1,1)出发只能向下或右走,终点为(n,m),B从(n,1)出发只能向上或右走,终点为(1,m)。两个人的速度不一样,走到的格子可以获的该格子的数,两人相遇的格子上的数两个人都不能拿。求A和B能拿到的数的总和的最大值。n,m<=1000
Input
The first line of the input contains two integers n and m (3 ≤ n, m ≤ 1000). Each of the next n lines contains m integers: j-th number from i-th line denotes element a[i][j] (0 ≤ a[i][j] ≤ 105).
Output
The output contains a single number — the maximum total gain possible.
Sample test(s)
input
3 3 100 100 100 100 1 100 100 100 100
output
800
Note
过程为a[1][1] → a[1][2] → a[2][2] → a[3][2] → a[3][3]. 加上路程 a[3][1] → a[2][1] → a[2][2] → a[2][3] → a[1][3].的答案
如果我们直接用暴力破解 由n的大小可知 一定是死路一条 2的m+n次方。而且还有两条路线 即使不考虑其他的操作步骤 2的(m+n+1)次方。直接死掉。
好吧 然后我们得换另一种方式来解决这个问题。
我们可以发现我们可以先预处理出每个格子到四个角落格子的路径最大数值,然后枚举两个人相遇的交点格子,枚举A、B的进来和出去方式,求最大值即可。
由我们预处理出每个格子到四个角落格子的路径最大数值,我们可以计算得每个可能被互相覆盖的点的公式为
注意:dp1 dp2 dp3 dp4为我们对预处理的记录结果
max{
result = Math.max(result, dp1[i-1][j]+dp2[i+1][j]+dp4[i][j-1]+dp3[i][j+1]);
result = Math.max(result, dp1[i][j-1]+dp2[i][j+1]+dp3[i-1][j]+dp4[i+1][j]);}
坑:
这里有个小关键点 可能是我一开始傻傻自己没有注意到
路线只有可能是这两种方式。即经过一个相同的点只能是横着过去 或者 竖直向下
(1)
1 | tow | one |
2 | 3/three | 4 |
five | four | 5 |
(2)
1 | 2 | one |
four | 3/three | two |
five | 4 | 5 |
好啦最后步骤上代码:
import java.util.Scanner;
public class Working {
public static int[][] dp1 = new int[1010][1010];
public static int[][] dp2 = new int[1010][1010];
public static int[][] dp3 = new int[1010][1010];
public static int[][] dp4 = new int[1010][1010];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int x = scanner.nextInt();
int y = scanner.nextInt();
int[][] arrays= new int[x+4][y+4];
for (int i = 1; i <= x; i++) {
for (int j = 1; j <= y; j++) {
arrays[i][j] = scanner.nextInt();
}
}
for (int i = 1; i <= x; i++) {
for (int j = 1; j <= y; j++) {
dp1[i][j] = Math.max(arrays[i-1][j], arrays[i][j-1])+arrays[i][j];
}
}
for (int i = x; i >= 1; i--) {
for (int j = y; j >= 1; j--) {
dp2[i][j] = Math.max(arrays[i][j+1], arrays[i+1][j])+arrays[i][j];
}
}
for (int i = x; i >= 1; i--) {
for (int j = 1; j <= y; j++) {
dp4[i][j] = Math.max(arrays[i][j-1], arrays[i+1][j])+arrays[i][j];
}
}
for (int i = 1; i <= x; i++) {
for (int j = y; j >= 1; j--) {
dp3[i][j] = Math.max(arrays[i-1][j], arrays[i][j+1])+arrays[i][j];
}
}
int result = 0;
for (int i = 1; i <= x; i++) {
for (int j = 1; j <= y; j++) {
result = Math.max(result, dp1[i-1][j]+dp2[i+1][j]+dp4[i][j-1]+dp3[i][j+1]);
result = Math.max(result, dp1[i][j-1]+dp2[i][j+1]+dp3[i-1][j]+dp4[i+1][j]);
}
}
System.out.println(result);
scanner.close();
}
}
好啦 今天的分享到此结束 欢迎大家多多指点。