>Link
luogu P7472
>解题思路
根据题意,每一条路径都会通过第一行的某个点,且每条路径对应的点都不重合,所以我们可以只枚举第一行的点来表示每两条路径相匹配。
把当前两条路径与第一行的交点的横坐标设为 x x x、 y y y,通过观察可以发现,当 x x x 和 y y y 奇偶性一样时,这两条路径才会相交,这时我们减去相交的1/2/4个点的值就行。
我比赛的时候把整个图斜着放处理了每一行每一列的和,其实可以直接预处理暴力模拟每条路径的值,不过能过就xing👍
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1010
using namespace std;
int n, a[2 * N][2 * N], b[2 * N][2 * N];
int sh[2 * N], sl[2 * N], ans, sum;
int main()
{
freopen ("pacman.in", "r", stdin);
freopen ("pacman.out", "w", stdout);
scanf ("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) scanf ("%d", &a[i][j]);
for (int i = 1; i < 2 * n; i++)
for (int j = 1; j <= i; j++)
{
if (i - j + 1 < 1 || i - j + 1 > n) continue;
sh[i] += a[i - j + 1][j];
b[i][n - i + 1 + 2 * (j - 1)] = a[i - j + 1][j];
}
for (int i = 1; i < 2 * n; i++)
for (int j = 1; j <= i; j++)
{
if (n - j + 1 < 1 || n - j + 1 > n) continue;
sl[i] += a[n - j + 1][i - j + 1];
}
for (int i = 1; i < n; i++)
for (int j = i + 1; j <= n; j++)
{
sum = 0;
if (i == 1) sum += sl[n];
else
{
sum += sh[i] + sh[2 * n - i];
sum += sl[n + i - 1] + sl[n - i + 1];
sum -= a[1][i] + a[i][1];
sum -= a[n - i + 1][n] + a[n][n - i + 1];
}
if (j == n) sum += sh[n];
else
{
sum += sh[j] + sh[2 * n - j];
sum += sl[n + j - 1] + sl[n - j + 1];
sum -= a[1][j] + a[j][1];
sum -= a[n - j + 1][n] + a[n][n - j + 1];
}
if ((i & 1 && j & 1) || (!(i & 1 || j & 1)))
{
sum -= b[j][n + i - 1];
if (n + i - 1 != n - i + 1) sum -= b[j][n - i + 1];
if (j != 2 * n - j) sum -= b[2 * n - j][n + i - 1];
if (j != 2 * n - j && n + i - 1 != n - i + 1)
sum -= b[2 * n - j][n - i + 1];
}
ans = max (ans, sum);
}
printf ("%d", ans);
return 0;
}