【bzoj 入门OJ】[NOIP 热身赛]Problem B: escape(二分答案+bfs)
Problem B: escape
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 168 Solved: 41
[Submit][Status][Web Board]
Description
给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2)。在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下你最少要走多少步才可以回到目标点。注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d)那么它们的距离为|a-c|+|b-d|
Input
第一行给出数字N,X,Y
第二行给出x1,y1,x2,y2
下面将有N行,给出N个敌人所在的坐标
第二行给出x1,y1,x2,y2
下面将有N行,给出N个敌人所在的坐标
Output
在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。
Sample Input
2 5 6
0 0 4 0
2 1
2 3
Sample Output
2 14
HINT
【题解】【二分答案+BFS】
【先将所有敌人的位置入队,由每个敌人开始扩展,求出所有点与敌人的最短距离,并将其中必经的起点和终点中小的一个距离作为二分答案的上界。】
【二分最小距离,每二分到一个答案len,就bfs判断在只经过距离敌人>=len的点是否能从起点走到终点。】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int q,n,m,x2,y2,x1,y1;
int dis[1010][1010],que[1000010][2],h,t,mxn;
int route[1010][1010],len,ans;
bool b[1010][1010];
inline bool check(int ll)
{
memset(route,127/3,sizeof(route));
memset(b,0,sizeof(b));
int last=route[0][0];
h=t=0; b[x2][y2]=1; route[x2][y2]=0;
que[++t][0]=x2; que[t][1]=y2;
while(h!=t)
{
h=(h%1000010)+1;
int x=que[h][0],y=que[h][1];
if(x==x1&&y==y1) break;
for(int i=0;i<4;++i)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(xx>=0&&xx<n&&yy>=0&&yy<m&&dis[xx][yy]>=ll)
if(route[xx][yy]>route[x][y]+1)
{
route[xx][yy]=route[x][y]+1;
if(!b[xx][yy])
{
t=(t%1000010)+1;
que[t][0]=xx; que[t][1]=yy;
b[xx][yy]=1;
}
}
}
}
return (route[x1][y1]==last);
}
inline void qsort(int l,int r)
{
int mid;
while(l<=r)
{
mid=(l+r)>>1;
if(!check(mid))
l=mid+1,ans=mid,len=route[x1][y1];
else r=mid-1;
}
}
int main()
{
//freopen("int.txt","r",stdin);
//freopen("my.txt","w",stdout);
int i,j;
memset(dis,127/3,sizeof(dis));
scanf("%d%d%d",&q,&n,&m);
scanf("%d%d%d%d",&x2,&y2,&x1,&y1);
for(i=1;i<=q;++i)
{
int x,y;
scanf("%d%d",&x,&y);
que[++t][0]=x; que[t][1]=y;
dis[x][y]=0; b[x][y]=1;
}
while(h!=t)
{
h=(h%1000010)+1;
int x=que[h][0],y=que[h][1];
for(i=0;i<4;++i)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(xx>=0&&xx<n&&yy>=0&&yy<m)
if(dis[xx][yy]>dis[x][y]+1)
{
dis[xx][yy]=dis[x][y]+1;
if(!b[xx][yy])
{
b[xx][yy]=1;
t=(t%1000010)+1;
que[t][0]=xx; que[t][1]=yy;
}
}
}
}
mxn=min(dis[x2][y2],dis[x1][y1]);
qsort(0,mxn);
printf("%d %d\n",ans,len);
return 0;
}
既然无能更改,又何必枉自寻烦忧