*51nod 1409

https://blog.csdn.net/stay_accept/article/details/81476358

不懂啊

#include <map>
#include <queue>
#include <string>
#include <math.h>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
inline bool scan_d(int &num)  {
    char in;
    bool IsN=false;
    in=getchar();
    if(in==EOF) return false;
    while(in!='-'&&(in<'0'||in>'9')) in=getchar();
    if(in=='-') {
        IsN=true;
        num=0;
    } else num=in-'0';
    while(in=getchar(),in>='0'&&in<='9') {
        num*=10,num+=in-'0';
    }
    if(IsN) num=-num;
    return true;
}
const int siz=1005;
int a[siz][siz];
long long g[siz],dp[2][siz][2];
int main() {
    long long ans;
    int n,m,i,j,k,x,y,op;
    while(scanf("%d%d",&n,&m)!=EOF) {           //dp[i][j][k]表示到dii列第j行向上走还是向下走
        for(i=1; i<=n; i++)
            for(j=1; j<=m; j++)
                scan_d(a[i][j]);
        for(i=1; i<=n; i++)
            dp[0][i][0]=dp[0][i][1]=0;
        for(i=1; i<=m; i++) {
            x=i&1,y=1-(i&1);
            for(j=1; j<=n; j++)
                dp[x][j][0]=dp[x][j][1]=-1;
            dp[x][0][0]=dp[x][0][1]=0;
            dp[x][n+1][0]=dp[x][n+1][1]=0;
            for(j=1; j<=n; j++) {
                if(a[j][i]==-1)
                    continue;
                for(k=0; k<=1; k++) {
                    if(dp[y][j][k]!=-1)
                        dp[x][j][0]=max(dp[x][j][0],dp[y][j][k]+a[j][i]);
                    if(dp[y][j][k]!=-1)
                        dp[x][j][1]=max(dp[x][j][1],dp[y][j][k]+a[j][i]);
                }
            }                                   //先算出从前一列过来的得分
            for(j=2; j<=n; j++) {
                if(dp[x][j-1][0]!=-1&&a[j][i]!=-1)
                    dp[x][j][0]=max(dp[x][j][0],dp[x][j-1][0]+a[j][i]);
            }                                   //然后本列进行转移
            for(j=1; j<=n; j++)
                g[j]=-1;
            g[0]=0;
            if(dp[x][n][0]!=-1) {               //算出经过传送门的得分
                op=n;                           //想下走就找尽可能往下更新的点
                while(op>1) {
                    if(dp[x][op][0]==dp[x][op-1][0]+a[op][i]&&dp[x][op-1][0]!=-1)
                        op--;
                    else
                        break;
                }
                for(j=1; j<op; j++) {
                    if(a[j][i]==-1)
                        break;
                    g[j]=g[j-1]+a[j][i];
                }
            }                                   //往上走跟往下走是一样的思路
            for(j=1; j<n; j++)
                dp[x][j][0]=max(dp[x][j][0],g[j]);
            for(j=n-1; j>=1; j--) {
                if(dp[x][j+1][1]!=-1&&a[j][i]!=-1)
                    dp[x][j][1]=max(dp[x][j][1],dp[x][j+1][1]+a[j][i]);
            }
            for(j=0; j<=n; j++)
                g[j]=-1;
            g[n+1]=0;
            if(dp[x][1][1]!=-1) {
                op=1;
                while(op<n) {
                    if(dp[x][op][1]==dp[x][op+1][1]+a[op][i]&&dp[x][op+1][1]!=-1)
                        op++;
                    else
                        break;
                }
                for(j=n; j>op; j--) {
                    if(a[j][i]==-1)
                        break;
                    g[j]=g[j+1]+a[j][i];
                }
            }
            for(j=n; j>1; j--)
                dp[x][j][1]=max(dp[x][j][1],g[j]);
        }
        ans=-1;
        for(i=1; i<=n; i++)
            ans=max(ans,max(dp[m&1][i][0],dp[m&1][i][1]));
        printf("%I64d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shandongs1/p/9451169.html