Codeforces 762D Maximum path 动态规划

Codeforces 762D

题目大意:

给定一个\(3*n(n \leq 10^5)\)的矩形,从左上角出发到右下角,规定每个格子只能经过一遍。经过一个格子会获得格子中的权值。每个格子的权值\(a_{ij}\)满足\(-10^9 \leq a_{ij} \leq 10^9\).最大化收益

题解:

乍一看,好麻烦
最主要的是因为他能够往回走.
但是我们画图可以发现:每次往回走一定不用超过1次.
也就是说,最多只能走成这样
5889f9489e7d2.png
而不会走成这样
5889f9489ef4c.png
因为下图的走法一定可以用上图组合,并且
由于只用3行的特性,每次向回走实际上是取走了所有的数.
所以我们只采用上图方式得出来的答案一定最优

所以我们O(n)线性递推即可
\(f[i][j]\)为到达第i列第j行的最大收益
方程比较多,就不写了,自己看代码吧。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &x){
    x=0;char ch;bool flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
template<typename T>inline T cat_max(const T &a,const T &b){return a>b ? a:b;}
template<typename T>inline T cat_min(const T &a,const T &b){return a<b ? a:b;}
const int maxn = 100010;
ll w[maxn][6],f[maxn][6],g[maxn][6];
int main(){
    int n;read(n);
    for(int i=1;i<=n;++i) read(w[i][1]);
    for(int i=1;i<=n;++i) read(w[i][2]);
    for(int i=1;i<=n;++i) read(w[i][3]);
    f[1][1] = w[1][1];
    f[1][2] = w[1][1] + w[1][2];
    f[1][3] = w[1][1] + w[1][2] + w[1][3];
    g[1][1] = w[1][1];g[1][2] = w[1][2];g[1][3] = w[1][3];
    for(int i=2;i<=n;++i){
        f[i][1] = g[i][1] = f[i-1][1] + w[i][1];
        f[i][2] = g[i][2] = f[i-1][2] + w[i][2];
        f[i][3] = g[i][3] = f[i-1][3] + w[i][3];
        f[i][1] = cat_max(f[i][1],g[i][2] + w[i][1]);
        f[i][1] = cat_max(f[i][1],g[i][3] + w[i][2] + w[i][1]);
        f[i][2] = cat_max(f[i][2],g[i][1] + w[i][2]);
        f[i][2] = cat_max(f[i][2],g[i][3] + w[i][2]);
        f[i][3] = cat_max(f[i][3],g[i][2] + w[i][3]);
        f[i][3] = cat_max(f[i][3],g[i][1] + w[i][2] + w[i][3]);
        f[i][1] = cat_max(f[i][1],g[i-1][3] + w[i][3] + w[i][2] + w[i-1][2] + w[i-1][1] + w[i][1]);
        f[i][3] = cat_max(f[i][3],g[i-1][1] + w[i][1] + w[i][2] + w[i-1][2] + w[i-1][3] + w[i][3]);
    }
    printf("%I64d",f[n][3]);
    getchar();getchar();
    return 0;
}

转载于:https://www.cnblogs.com/Skyminer/p/6352093.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值