題目大意: n×n 棋盤,每格有權值。放兩個主教,要求它們攻擊的格子不重疊(即一個在黑格、一個在白格),最大化兩主教攻擊格子權值之和。輸出最大值及兩主教位置。
(x+y) % 2 不同。g[i][j]。zhu[i - j + n] 存主對角線和(偏移 n 避免負下標)。fu[i + j] 存副對角線和。sum = zhu[i-j+n] + fu[i+j] - g[i][j](減去自身重複計算)。(i+j)%2 更新黑格最大值 b 或白格最大值 w,記錄位置。b + w 及兩主教座標(1-based)。#include <cstdio>
#include <cstring>
const int N = 2005;
typedef long long ll;
int n;
ll g[N][N], zhu[N + N], fu[N + N];
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%lld", &g[i][j]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
zhu[i - j + n] += g[i][j];
fu[i + j] += g[i][j];
}
}
ll b = -1, w = -1;
int bx, by, wx, wy;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
ll sum = zhu[i - j + n] + fu[i + j] - g[i][j];
if ((i + j) % 2 == 0) {
if (b < sum) { b = sum; bx = i + 1; by = j + 1; }
} else {
if (w < sum) { w = sum; wx = i + 1; wy = j + 1; }
}
}
}
printf("%lld\n", b + w);
printf("%d %d %d %d\n", bx, by, wx, wy);
return 0;
}
時間 O(n²),空間 O(n)。n ≤ 2000,完全滿足限制。
g[i][j] 導致雙計自身權值。long long 存儲對角線和與答案(權值上限 10⁹,n=2000 時和可達 4×10¹²)。-(n-1) ~ (n-1),偏移 n 後下標 1 ~ 2n-1,開陣列 2n+5 即可。