Description
小FF的第一片矿区已经开始运作了, 他着手开展第二片矿区……小FF的第二片矿区, 也是"NewBe_One"计划的核
心部分, 因为在这片矿区里面有全宇宙最稀有的两种矿物,科学家称其为NEW矿和BE矿。矿区是被划分成一个n*m
的矩形区域。 小FF探明了每一小块区域里的NEW矿和BE矿的蕴藏量, 并且小FF还在矿区的北边和西边分别设置了N
EW矿和BE矿的收集站。你的任务是设计一个管道运输系统,使得运送的NEW矿和BE矿的总量最多。管道的型号有两
种,一种是东西向,一种是南北向。在一个格子内你能建造一种管道,但不能两种都建。如果两个同类型管道首位
相接,它们就可以被连接起来。另外这些矿物都十分不稳定,因此它们在运送过程中都不能拐弯。这就意味着如果
某个格子上建有南北向管道,但是它北边的格子建有东西向管道,那么这根南北向管道内运送的任何东西都将丢失
。进一步地,运到NEW矿收集站的BE矿也会丢失,运到BE矿收集站的NEW矿也会丢失。
Input
第一行包含两个整数n和m,表示矿区大小。
以下n行,每行m个整数,其中第i行第j个整数G[ i , j ] 描述各个格子上的BE矿数量。
接下来以类似的矩阵表示各个格子上的NEW矿数量。
0<= n, m <=1000;
0<= G[ i, j ] <=1000.
Output
仅一个整数, 表示最多可以采集到的NEW矿和BE矿的总量。
Sample Input
4 4 0 0 10 9 1 3 10 0 4 2 1 3 1 1 20 0 10 0 0 0 1 1 1 30 0 0 5 5 5 10 10 10
Sample Output
98
分析
此题考虑使用DP
首先,我们横向,纵向分别求前缀和
状态设计成三
dp[ i ][ j ][0]描述以( i, j )为右下角的矩阵范围内能采到的最多的BE矿
dp[ i ][ j ][1]描述以( i, j )为右下角的矩阵范围内能采到的最多的NEW矿
那么就可以很愉快地得到状态转移方程
dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1]) + a[i][j];
dp[i][j][1] = max(dp[i][j - 1][0], dp[i][j - 1][1]) + b[i][j];
这样一来最后的答案就是
max(dp[n][m][0], dp[n][m][1])
注意开long long
代码
#include<bits/stdc++.h>
using namespace std;
long long n, m;
long long a[1010][1010], b[1010][1010];
long long dp[1010][1010][4];
inline long long read() {
long long x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
return x * f;
}
int main() {
n = read(), m = read();
for (long long i = 1; i <= n; i++) {
for (long long j = 1; j <= m; j++) {
a[i][j] = a[i][j - 1] + read();
}
}
for (long long i = 1; i <= n; i++) {
for (long long j = 1; j <= m; j++) {
b[i][j] = b[i - 1][j] + read();
}
}
for (long long i = 1; i <= n; i++) {
for (long long j = 1; j <= m; j++) {
dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1]) + a[i][j];
dp[i][j][1] = max(dp[i][j - 1][0], dp[i][j - 1][1]) + b[i][j];
}
}
printf("%lld", max(dp[n][m][0], dp[n][m][1]));
return 0;
}