题解 P7472 [NOI Online 2021 入门组] 吃豆人
首先看数据范围
画图观察一下,发现对于每个边上的点,是具有确定性的,无论从哪个方向出发,均有且仅有一种矩阵能包含边上的点,于是考虑以边上的点确定每一个不同的矩阵。
容易看出每个点出发的矩阵都会绕一圈回到该点,每个矩阵边上的点数量不超过
需要注意会有线状的矩阵,不能重复加两次,需要特判一下。
枚举任意两个矩阵,发现所选的两个矩阵还可能会有重复的部分需要减去,这里需要分类讨论。
设选择的矩阵分别包含第一行的第
-
当
为奇数时, 。此时这两个矩阵不会有公共点,原因是它们的中点不是整数,其交点纵坐标也不是整数。 -
当
为偶数且 时, 。两个矩阵皆为线状,只有一个交点在矩阵中心。 -
当
为偶数且 和 仅满足任意一条件时, 。这是仅一个矩阵为线状时的情况,结论貌似很难懂,但画画图就发现纵坐标和中点有关,然后就很好理解了。 -
当
为偶数且 时, 。实质上就是满足了正方形的对称性,互换了下横纵坐标即为另外两个的交点。
总体时间复杂度为
#include <bits/stdc++.h>
using namespace std;
const int kx[] = {1, 1, -1, -1}, ky[] = {-1, 1, 1, -1};
const int N = 1e3 + 10;
int n, a[N][N], c[N], ans;
bool vis[N][N];
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 <= n; i++)
c[1] += a[i][i], c[n] += a[i][n - i + 1];
for(int i = 2; i < n; i++) {
int x = 1, y = i, op = 0, sum = 0;
bool flag = false;
for(;;) {
if(x == 1 && y == i && flag) {
c[i] = sum;
break;
}
sum += a[x][y];
flag = true;
if(x + kx[op] <= 0 || x + kx[op] > n || y + ky[op] <= 0 || y + ky[op] > n)
op++;
x += kx[op], y += ky[op];
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
if(i == j)
continue;
int mx = max(i, j), mn = min(i, j);
if((mx - mn) & 1) {
ans = max(ans, c[i] + c[j]);
}
else if(mn == 1 && mx == n) {
int t = c[i] + c[j] - a[(i + j) / 2][(i + j) / 2];
ans = max(ans, t);
}
else {
int t = c[i] + c[j];
t -= a[1 + (mx - mn) / 2][(i + j) / 2];
t -= a[n - (mx - mn) / 2][n - (i + j) / 2 + 1];
if(mn == 1 || mx == n)
ans = max(ans, t);
else {
t -= a[(i + j) / 2][1 + (mx - mn) / 2];
t -= a[n - (i + j) / 2 + 1][n - (mx - mn) / 2];
ans = max(ans, t);
}
}
}
printf("%d", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话