思路
- 由于障碍物都在一个很小的区间内我们可以分开处理。
- 由于路径是可逆的,我们可以算每个点到原点的距离
- 先处理区间的边框后再处理边框外的点(可以用公式计算的复杂度)
#include<bits/stdc++.h>
#define For(i,a,b) for(int (i)=(a);(i)<=(b);++(i))
using namespace std;
const int N=2e3+2,M=2e3+5,n=1e3+1;
struct P{int x,y;}Q[M*M],x,y;
bool vis[M][M];
int dis[M][M],s,b,l,r;
int rx[]={0,1,0,-1},ry[]={1,0,-1,0};
long long cnt[2];
inline bool check(int x,int y){
return x>=0&&y>=0&&x<=N&&y<=N&&!vis[x][y];
}
inline int get(int x,int y){
int a=y/2,b=y-y/2;
if(x&1)cnt[0]+=b,cnt[1]+=a;
else cnt[1]+=b,cnt[0]+=a;
}
/*********对于四角的我们可以通过枚举步数形成一个三角形来计算*********/
inline void Calc(int x,int y){
if(dis[x][y]==-1||dis[x][y]>s)return;
for(int i=0;i<=s-dis[x][y];i++){
get(dis[x][y]+i,s-dis[x][y]-i);
if(i)cnt[(dis[x][y]+i)&1]++;
}
}
inline void calc(int x,int y){
if(dis[x][y]==-1||dis[x][y]>s)return;
get(dis[x][y],s-dis[x][y]);
}
int main(){
memset(dis,-1,sizeof(dis));
scanf("%d %d",&b,&s);
vis[n][n]=1,dis[n][n]=0;
int x,y;
while(b--)scanf("%d %d",&x,&y),vis[x+n][y+n]=1;
Q[r++]=(P){n,n};
/*********BFS预处理出到达边缘的点的最小步数*********/
while(l<r){
P x=Q[l++];
cnt[dis[x.x][x.y]&1]++;
if(dis[x.x][x.y]>=s)continue;
for(int i=0;i<4;i++){
P y=(P){x.x+rx[i],x.y+ry[i]};
if(check(y.x,y.y)){
dis[y.x][y.y]=dis[x.x][x.y]+1;
vis[y.x][y.y]=1;
Q[r++]=y;
}
}
}
/*********先计算上下左右的直接暴力枚举*********/
For(i,1,N-1)calc(i,0),calc(0,i),calc(i,N),calc(N,i);
/*********先计算四角的*********/
Calc(0,0),Calc(0,N),Calc(N,0),Calc(N,N);
printf("%lld %lld\n",cnt[0],cnt[1]);
return 0;
}