方格取数(number) 题解(dp)

题目链接

题目大意

给你n*m个方格,每个格子有对应的值

你从(1,1)出发到(n,m)每次只能往下往上往右,走过的点则不能走

求一条路线使得走过的路径的权值和最大

题目思路

如果只是简单的往下和往右走就是直接dp

而如果是可以往上走,那么就要设置dp维度

(dp[i][j][0]代表(i,j)从左转移下来)

(dp[i][j][1]代表(i,j)从上转移下来)

(dp[i][j][2]代表(i,j)从下转移下来)

这个dp显然循环是要从先枚举列,再枚举行

预处理第一列,求答案即可

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e3+5;
int n,m;
int a[maxn][maxn];
ll dp[maxn][maxn][3];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    memset(dp,-0x3f,sizeof(dp));
    dp[0][1][1]=0;
    for(int i=1;i<=n;i++){
        dp[i][1][1]=dp[i-1][1][1]+a[i][1];
    }
    for(int j=2;j<=m;j++){
        for(int i=1;i<=n;i++){
            dp[i][j][0]=max({dp[i][j-1][0],dp[i][j-1][1],dp[i][j-1][2]})+a[i][j];
        }
        for(int i=2;i<=n;i++){
            dp[i][j][1]=max({dp[i-1][j][0],dp[i-1][j][1]})+a[i][j];
        }
        for(int i=n-1;i>=1;i--){
            dp[i][j][2]=max({dp[i+1][j][2],dp[i+1][j][0]})+a[i][j];
        }
    }
    printf("%lld
",max(dp[n][m][1],dp[n][m][0]));
    return 0;
}

卷也卷不过,躺又躺不平
原文地址:https://www.cnblogs.com/hunxuewangzi/p/13956143.html