题目概述
给出 3×n 的带权网格,从 (0,1) 开始走,一个格子只能走到相邻(上下左右)格子且不能被重复走,求到 (2,n) 的最大权值。
解题报告
我们会发现如果回头走了两个格子,一定可以被回头走了一个格子(或不回头)的方案替换掉。
所以我们只需要考虑回头走了一个格子。
考虑DP,定义
f[0/1/2/3][j]
表示第
j
列走完,目前在
则
示例程序
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100000;
int n,a[3][maxn+5];LL f[4][maxn+5];
inline LL Sum(int j,int L,int R)
{
if (L>R) swap(L,R);LL sum=0;
for (int i=L;i<=R;i++) sum+=a[i][j];
return sum;
}
int main()
{
scanf("%d",&n);
for (int i=0;i<3;i++)
for (int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
memset(f,192,sizeof(f));f[0][0]=0;
for (int j=1;j<=n;j++)
{
for (int i=0;i<3;i++)
for (int k=0;k<3;k++)
f[i][j]=max(f[i][j],f[k][j-1]+Sum(j,i,k));
f[0][j]=max(f[0][j],f[3][j-1]+Sum(j,0,2));
f[2][j]=max(f[2][j],f[3][j-1]+Sum(j,0,2));
f[3][j]=max(f[3][j],max(f[0][j-1],f[2][j-1])+Sum(j,0,2));
}
return printf("%lld\n",f[2][n]),0;
}