[BZOJbegin][NOIP十连测热身赛b]escape(二分+bfs)

来源:互联网 发布:北大青鸟网络培训课程 编辑:程序博客网 时间:2024/06/11 04:14

题目描述

传送门

题解

预处理每一个点到离它最近的敌人的距离。
二分答案,判定的时候也用bfs,只有不在距离范围内的点才能走。

代码

#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;#define N 1005int sx[4]={0,0,1,-1}; int sy[4]={1,-1,0,0};int n,x,y,x1,y1,x2,y2,inf,ans,sum,cnt;struct hp{int x,y;}pt[N*10];int dis[N][N],step[N][N];queue <hp> q;bool check(int mid){    if (dis[x1][y1]<mid) return false;    while (!q.empty()) q.pop();    q.push((hp){x1,y1});    memset(step,127,sizeof(step));    step[x1][y1]=0;    while (!q.empty())    {        hp now=q.front(); q.pop();        for (int i=0;i<4;++i)        {            int u=now.x+sx[i],v=now.y+sy[i];            if (u<0||v<0||u>x||v>y||dis[u][v]<mid||step[u][v]!=inf) continue;            step[u][v]=step[now.x][now.y]+1;            if (u==x2&&v==y2)            {                cnt=step[u][v];                return true;            }            q.push((hp){u,v});        }    }    return false;}void find(){    int l=0,r=2000,mid;    while (l<=r)    {        mid=(l+r)>>1;        if (check(mid)) ans=mid,sum=cnt,l=mid+1;        else r=mid-1;    }}int main(){    scanf("%d%d%d",&n,&x,&y); x--; y--;    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);    memset(dis,127,sizeof(dis));inf=dis[0][0];    for (int i=1;i<=n;++i)    {        scanf("%d%d",&pt[i].x,&pt[i].y);        q.push((hp){pt[i].x,pt[i].y});        dis[pt[i].x][pt[i].y]=0;    }    while (!q.empty())    {        hp now=q.front(); q.pop();        for (int i=0;i<4;++i)        {            int u=now.x+sx[i],v=now.y+sy[i];            if (u<0||v<0||u>x||v>y||dis[u][v]!=inf) continue;            dis[u][v]=dis[now.x][now.y]+1;            q.push((hp){u,v});        }    }    find();    printf("%d %d\n",ans,sum);}
0 0
原创粉丝点击