luoguP7074(CSP-J2)方格取数题解

题面点这里

题面简述:给你一个 $ 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}}) + a_{i,j} $ ;

$ f_{i,j,1} = \max ({f_{i+1,j,1},f_{i,j-1,0/1}}) + a_{i,j} $ ;

答案就是 $ 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;
}
posted @ 2020-12-03 21:46  b1ts  阅读(106)  评论(0编辑  收藏  举报