注意上式只有在$(X_P+X_Q)\bmod 2=0$的时候成立,因此我们需要判一下。进而可求$B,C,D$这里有一个要点,$A,B,C,D$可能有重复的点,这时只需要判一下就可以了。
从大到小枚举所有路径,两两配对,去重后比较大小就可以了。
不过,还可以做个小优化,用$Max$存储当前最大值,如果枚举到的路径的豆子数小于当前$Max$值,就跳出循环,因为我们是从小到大枚举的。
上代码:
~~~cpp
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int ans=0,n,bean[1005][1005],h[5]={0,1,1,-1,-1},l[5]={0,1,-1,-1,1};
struct A {
int ret,x1,y1;
}add[1005];
bool cmp (A x,A y) {
return x.ret>y.ret;
}
int main () {
scanf ("%d",&n);
for (int i=1;i<=n;++i) {
for (int j=1;j<=n;++j) {
scanf ("%d",&bean[i][j]);
}
}
for (int i=1;i<=n;++i) {
int x=1,y=i,cnt=1;
add[i].x1=1;
add[i].y1=i;
do {
add[i].ret+=bean[x][y];
if ((x==n&&y==1)||(x==n&&y==n)) break;
x+=h[cnt];
y+=l[cnt];
if (x<1||x>n||y<1||y>n) {
x-=h[cnt];
y-=l[cnt++];
if (cnt>4) cnt=1;
x+=h[cnt];
y+=l[cnt];
}
}while (x!=1||y!=i); //暴力求所有路径的豆子数
}
sort (add+1,add+n+1,cmp); //从小到大排序
for (int i=1;i<=n;++i) {
if (i+1<=n&&add[i].ret+add[i+1].ret<=ans) break;
for (int j=i+1;j<=n;++j) {
if (ans>=add[i].ret+add[j].ret) break;
int Ret=add[i].ret+add[j].ret;
int y=abs(add[i].y1-add[j].y1);
if (y&1) ans=max(ans,Ret);
else { //去重
int y2=(add[i].y1+add[j].y1)/2,x2=1+y/2;
Ret-=bean[x2][y2];
if (x2!=y2) Ret-=bean[y2][x2];
int x3=n-x2+1;
int y3=n-y2+1;
if ((x3!=x2||y3!=y2)&&(x3!=y2||y3!=x2)) {
Ret-=bean[x3][y3];
if (x3!=y3) Ret-=bean[y3][x3];
}
ans=max(ans,Ret);
}
}
}
printf ("%d",ans);
return 0;
}
~~~