马里奥派对

思路

  • 由于障碍物都在一个很小的区间内我们可以分开处理。
    • 由于路径是可逆的,我们可以算每个点到原点的距离
    • 先处理区间的边框后再处理边框外的点(可以用公式计算的复杂度)
/*
    先用BFS计算出原地到边框的最距离
    之后把图像分成了上下左右和四个角
    上下左右的点直接走到边上即可
    四个角点区域,先到达顶点,再走向原点即可。
    因为四个边框外没有障碍物故到任何点都是一样的
*/
#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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值