题目描述
给出数字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|。
输入:
第一行给出数字N,X,Y
第二行给出x1,y1,x2,y2
下面将有N行,给出N个敌人所在的坐标
输出:
在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。
Sample input
2 5 6
0 0 4 0
2 1
2 3
Sample output
2 14
题解
搜索+二分判定,考试时脑子秀逗了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int n,xs,ys,xe,ye,X,Y;
struct diren{int x,y;} d[10002],q[1000002];
int map[1002][1002],ct[1002][1002],minl,ans;
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
void init()
{
scanf("%d%d%d",&n,&X,&Y);
scanf("%d%d%d%d",&xs,&ys,&xe,&ye);
int i;
for(i=1;i<=n;i++) scanf("%d%d",&d[i].x,&d[i].y);
}
void pre()
{
int i,t=0,w=0,xn,yn,xt,yt;
memset(map,-1,sizeof(map));
for(i=1;i<=n;i++)
{q[w].x=d[i].x; q[w].y=d[i].y; w++;
map[d[i].x][d[i].y]=0;
}
while(t<w)
{xn=q[t].x; yn=q[t].y; t++;
for(i=0;i<4;i++)
{xt=xn+xx[i]; yt=yn+yy[i];
if(xt<0||xt>=X||yt<0||yt>=Y||map[xt][yt]!=-1) continue;
map[xt][yt]=map[xn][yn]+1;
q[w].x=xt; q[w].y=yt; w++;
}
}
}
bool check(int x,int y,int jl)
{
if(x<0||x>=X||y<0||y>=Y||map[x][y]<jl) return false;
if(ct[x][y]!=-1) return false;
return true;
}
bool find(int jl)
{
int t=0,w=1,i,xn,yn,xt,yt;
//if(map[xs][ys]<jl) return false;
memset(ct,-1,sizeof(ct));
q[t].x=xs; q[t].y=ys; ct[xs][ys]=0;
while(t<w)
{xn=q[t].x; yn=q[t].y; t++;
for(i=0;i<4;i++)
{xt=xn+xx[i]; yt=yn+yy[i];
if(!check(xt,yt,jl)) continue;
ct[xt][yt]=ct[xn][yn]+1;
if(xt==xe&&yt==ye) {minl=jl; ans=ct[xt][yt]; return true;}
q[w].x=xt; q[w].y=yt; w++;
}
}
return false;
}
void work()
{
pre();
int l=0,r=map[xs][ys],mid;
while(l<=r)
{mid=(l+r)>>1;
if(find(mid)) l=mid+1;
else r=mid-1;
}
printf("%d %d\n",minl,ans);
}
int main()
{
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
init(); work();
return 0;
}