luoguP7074(CSP-J2)方格取數題解
阿新 • • 發佈:2020-12-04
題面簡述:給你一個 $ n \times m $ 的矩陣,從左上角走到右下角,每次可以向上,下,右三個方向走,問所能取到數的和的最大值。
資料範圍:$ 1\leq n,m \leq 10^3 , -10^4 \leq a_{i,j} \leq 10^4 $ 。
題解:
一看就是直接線性DP。
設 $ f_{i,j,0} $ 表示在第 $ j $ 列向下走所能取得的數的最大值,$ f_{i,j,1} $ 表示在第 $ j $ 列向上走所能取得的數的最大值。
於是轉移方程就很顯然了,直接擺在這裡,就不解釋了。
$ f_{i,j,0} = \max {f_{i-1,j,0},f_{i,j-1,0/1}} $ ;
$ f_{i,j,1} = \max {f_{i+1,j,1},f_{i,j-1,0/1}} $ ;
答案就是 $ f_{n,m,0} $ 。
邊界什麼的具體看程式碼:
#include <bits/stdc++.h> using namespace std; #define max(x,y) ((x)>(y)?(x):(y)) #define int long long inline int read(){ int f=1,r=0;char c=getchar(); while(!isdigit(c))f^=c=='-',c=getchar(); while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar(); return f?r:-r; } const int N=1e3+5,inf=1e11; int n,m,a[N][N],f[N][N][2]; signed main(){ n=read(),m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(); for(int i=1;i<=n;i++)f[i][0][0]=f[i][0][1]=-inf;//因為有負數,所以設成-inf。 for(int i=2;i<=m;i++)f[0][i][0]=f[n+1][i][0]=f[0][i][1]=f[n+1][i][1]=-inf; for(int j=1;j<=m;j++){ if(j==1 || j==m)//第一列與第n列顯然只能往下走 for(int i=1;i<=n;i++)f[i][j][0]=max(f[i-1][j][0],max(f[i][j-1][0],f[i][j-1][1]))+a[i][j],f[i][j][1]=-inf; else{ for(int i=1;i<=n;i++) f[i][j][0]=max(max(f[i-1][j][0],f[i][j-1][0]),f[i][j-1][1])+a[i][j]; for(int i=n;i;i--) f[i][j][1]=max(max(f[i+1][j][1],f[i][j-1][1]),f[i][j-1][0])+a[i][j]; } } return cout<<f[n][m][0],0; }