题目
[USACO 20FEB] Equilateral Triangles P
分析
转换成切比雪夫距离过后,发现符合条件的点必然是正方形的两个顶点和其对边上的一个点,于是 O ( n 3 ) O(n^3) O(n3) 枚举两个点,前缀和算一算即可。
代码
之前不想转切比雪夫因为要平移坐标,瞎 78 写了一通 WA 穿了,调了一个小时过后重构代码,发现转成切比雪夫过后太好写了。事实上只需要输入的时候调整一下坐标并把 N N N 的值改了,之后完全正常算即可。
#include <bits/stdc++.h>
const int MAXN = 300;
int N, Ans;
char S[MAXN + 5];
int A[2 * MAXN + 5][2 * MAXN + 5];
int B[2 * MAXN + 5][2 * MAXN + 5];
int Cnt[2 * MAXN + 5][2 * MAXN + 5];
void Solve(int Mat[][2 * MAXN + 5], int d = 0) {
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
Cnt[i][j] = Cnt[i][j - 1] + Mat[i][j];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (Mat[i][j])
for (int k = j + 1; k <= N; k++) {
int x = i - (k - j), y = i + (k - j);
if(Mat[i][k]) {
if (x >= 1) Ans += Cnt[x][k - d] - Cnt[x][j - 1 + d];
if (y <= N) Ans += Cnt[y][k - d] - Cnt[y][j - 1 + d];
}
}
}
}
}
int main() {
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
scanf("%s", S + 1);
for (int j = 1; j <= N; j++)
if (S[j] == '*')
A[i + j - 1][i - j + N] = 1;
}
N = 2 * N - 1;
Solve(A);
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
B[j][N - i + 1] = A[i][j];
Solve(B, 1);
printf("%d", Ans);
return 0;
}