题目
Luogu
给定一些点坐标
计算曼哈顿意义下等边三角形个数
n
≤
400
n\le 400
n≤400
思路
转化成切比雪夫距离
转化后面积会扩大
2
\sqrt2
2 倍
然后发现
一个边框绕着另外一个边框平移必定经过和它同行同列的点
然后枚举两次计算即可
注意角上的点会被算两次
反转的的时候原来不能直接反转原坐标的点…
代码
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<cstdio>
#include<queue>
#include<cmath>
#include<vector>
#include<ctime>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}
return f*x;
}
#define MAXN 600
#define INF 0x3f3f3f3f
int ans;
char Map[MAXN+5][MAXN+5];
int n,s[MAXN+5][MAXN+5],tp,stk[MAXN+5];
void Cal(bool f){
memset(s,0,sizeof(s));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(Map[i][j]=='*'){
if(!f)
s[i+j-1][i-j+n]=1;//1,2n-1 1,2n-1
else s[i-j+n][i+j-1]=1;
}
for(int i=1;i<=2*n-1;i++)
for(int j=1;j<=2*n-1;j++)
s[i][j]+=s[i][j-1];
for(int h=1;h<=2*n-1;h++){
int tp=0;
for(int i=1;i<=2*n-1;i++)
if(s[h][i]-s[h][i-1])
stk[++tp]=i;
for(int i=1;i<=tp;i++)
for(int j=i+1;j<=tp;j++){
int t1=h+stk[j]-stk[i],t2=h-stk[j]+stk[i];
int tmp=ans;
if(t1<=2*n-1)
ans+=s[t1][stk[j]-f]-s[t1][stk[i]-1+f];
if(t2>=1)
ans+=s[t2][stk[j]-f]-s[t2][stk[i]-1+f];
}
}
return ;
}
int main(){
n=read();
for(int i=1;i<=n;i++)
scanf("%s",Map[i]+1);
Cal(0);
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
swap(Map[i][j],Map[j][i]);
Cal(1);
printf("%d\n",ans);
return 0;
}