//5476K 657MS G++
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 510;
int DP[MAX][MAX];
int ymap[MAX][MAX];
int bmap[MAX][MAX];
int H;
int W;
int ySum[MAX][MAX];
int bSum[MAX][MAX];
inline int max(int a, int b) {
return a > b ? a: b;
}
void preProcess() {
// getySum
for (int y = 1; y <= H; y++) {
for (int x = 1; x <= W; x++) {
if (x == 1) {
ySum[x][y] = ymap[x][y];
} else {
ySum[x][y] = ymap[x][y] + ySum[x-1][y];
}
}
}
// getbSum
for (int x = 1; x <= W; x++) {
for (int y = 1; y <= H; y++) {
if (y == 1) {
bSum[x][y] = bmap[x][y];
} else {
bSum[x][y] = bmap[x][y] + bSum[x][y-1];
}
}
}
}
void getMax() {
for (int y = 1; y <= H; y++) {
for (int x = 1; x <= W; x++) {
if (x == 1 && y == 1) {
DP[1][1] = max(ymap[1][1], bmap[1][1]);
} else if (x == 1) {
int choosey = DP[1][y-1] + ymap[x][y];
int chooseb = bSum[x][y];
DP[x][y] = max(choosey, chooseb);
} else if (y == 1) {
int choosey = ySum[x][y];
int chooseb = DP[x-1][1] + bmap[x][y];
DP[x][y] = max(choosey, chooseb);
} else {
int choosey = DP[x][y-1] + ySum[x][y];
int chooseb = DP[x-1][y] + bSum[x][y];
DP[x][y] = max(choosey, chooseb);
}
}
}
printf("%d\n", DP[W][H]);
}
int main() {
while(scanf("%d %d", &H, &W) != EOF) {
if (H == 0 && W == 0) {
return 0;
}
memset(DP, -1, sizeof(DP));
memset(ymap, 0, sizeof(ymap));
memset(bmap, 0, sizeof(bmap));
memset(ySum, 0, sizeof(ySum));
memset(bSum, 0, sizeof(bSum));
for (int y = 1; y <= H; y++) {
for (int x = 1; x <= W; x++) {
scanf("%d", &ymap[x][y]);
}
}
for (int y = 1; y <= H; y++) {
for (int x = 1; x <= W; x++) {
scanf("%d", &bmap[x][y]);
}
}
preProcess();
getMax();
}
}
妈的,又把一道简单DP题想复杂了,我为啥转化这么难呢?
刚看题就有点被懵着了,无从下手,最开始的分析还想复杂了,还想将任何的(x1, y1, x2, y2)矩形的最大采矿值给DP出来,但是一看到 矩形长宽最大能到500,
而四维DP所需的空间就是 500*500*500*500 绝壁MLE.
后来无奈搜了一下,欲哭无泪,又是一道基础DP题,只需求(0,0,x1,y1)的最大采矿值就可以了(注意最后在接收完输入以后,y矿的目的地将是y轴, b矿的目的地将是x轴,题目很贴心的不用再转换坐标了),并且也满足DP的递推关系:
case1: 如果 x1 == 1, y1 == 1, 那么直接取 ymap(y矿分布)[1][1] 和 bmap(b矿分布)[1][1]的最大就可以了。
case2: 如果x1 == 1, y1 > 1, 那么两个选择, 一个是挖y矿,以为y矿的目的地是y轴,那么其能挖的最大矿量是 ymap[x][y] + DP[x][y-1]
另外一个是挖b矿,那么必然会建立一条从(x,y)到 (x,1)的传送带,其矿量是此范围内的所有b矿的和(这个和要之前预处理出来, 不然TLE)
case3: 如果y1== 1, x1>1, 同case2, 反一下.
case4: 两个选择: 一个是挖y矿,然后 (x,y)<->(1,y)的y矿和 加上 DP[x][y-1]
另外就是挖b矿,然后 (x, y)<->(x, 1)的b矿和 加上 DP[x-1][y]
取最大值即可。
这里的思路等于是为矩形找了一个固定的顶点(0,0),然后开始逐个格子作为对应端点的枚举得到最大值,这样就没有我最开始思路的问题,并且还简单,这种思路在以后看到矩形的时候要想想,如何覆盖矩形其实不重要,不管是一点固定 还是 没有固定点,只要最后求出解就可以.