poj-2948

22 篇文章 0 订阅
//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),然后开始逐个格子作为对应端点的枚举得到最大值,这样就没有我最开始思路的问题,并且还简单,这种思路在以后看到矩形的时候要想想,如何覆盖矩形其实不重要,不管是一点固定 还是 没有固定点,只要最后求出解就可以.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值