LA 3530 Martian Mining 简单dp

题意:

给定一个n*m的矩阵, 每个方格中有a矿和b矿, 要求a矿只能从左到右运输, b矿只能从上到下运输, 求最大的运输量

分析:

这题还是很好做的,下面是我的代码,不过我写的状态好像复杂了,看到别人还有更简单的状态表示:d[i][j]表示到(i,j)可以得到的最优解。状态转移也比较容易:
dp[i][j]=max(dp[i][j-1]+sb[i][j],dp[i-1][j]+sa[i][j]) (sa,sb含义与我的代码含义相同)
吐槽:
比较坑爹的是我第一次交的时候WA了,然后我就检查错误,想了半天发现没有错误,于是把刚刚交的代码重交,居然过了,==好坑啊!

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int INF = 1e9 + 9;
const int N = 500 + 9;
int sa[N][N], sb[N][N], f[N][N][2], a;
/*
sa[i][j]第i行到从第1列到第j列的A矿的和
sb[i][j]第j列到从第1行到第i行的B矿的和
f[i][j][0]表示(i,j)这个位置放A矿的最大值和
f[i][j][1]表示(i,j)这个位置放B矿的最大值和
那么答案就是max (f[n][m][0], f[n][m][1])
*/
int main() {
    //freopen ("f.txt", "r", stdin);
    int n, m, a, b;
    while (~scanf ("%d%d", &n, &m) && (n + m) ) {
        memset (sa, 0, sizeof (sa) );
        memset (sb, 0, sizeof (sb) );
        memset (f, 0, sizeof (f) );
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) {
                scanf ("%d", &a);
                sa[i][j] = sa[i][j - 1] + a;
            }
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) {
                scanf ("%d", &b);
                sb[i][j] = sb[i - 1][j] + b;
            }

        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) {
                f[i][j][0] = max (f[i - 1][j - 1][0], f[i - 1][j - 1][1]) + sa[i][j] + sb[i - 1][j];
                f[i][j][0] = max (f[i][j][0], max (f[i - 1][j][1], f[i - 1][j][0]) + sa[i][j]);

                f[i][j][1] = max (f[i - 1][j - 1][0], f[i - 1][j - 1][1]) + sa[i][j - 1] + sb[i][j];
                f[i][j][1] = max (f[i][j][1], max (f[i][j - 1][0], f[i][j - 1][1]) + sb[i][j]);
            }

        printf ("%d\n", max (f[n][m][0], f[n][m][1]) );

    }
    return 0;
}
/*
SampleInput
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
0 0
SampleOutput
98

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值