标签:限制 多少 格式 pen 行号 -- alt blog nbsp
大逃亡(escape)
【问题描述】
给出数字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|。
【输入格式】
第一行3 个整数为N,X,Y
第二行4 个整数为x1,y1,x2,y2
下面将有N 行,为N 个敌人所在的坐标。
【输出格式】
在一行内输出你离敌人的距离及在这个距离的限制下,你到目标点最少要移动多少步。
【样例输入】
2 5 6
0 0 4 0
2 1
2 3
【样例输出】
2 14
最大化最小值,很明显二分后验证;
敌人位置固定,所以每一个点距最近敌人距离固定;
求曼哈顿距离,所以以每个敌人为起始点四连通bfs,每个点第一次一定是被最近的敌人访问;
复杂度方面,每个点只会被上下左右四个点各访问一次,所以预处理是O(4*n^2);
预处理后直接bfs全图验证,复杂度O(n^2);
AC GET☆DAZE
代码 ↓
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define MAX_N 39393939 #define ll long long using namespace std; struct poi { ll x,y; }; ll sum=0; poi que[1000039]; ll ansdis[1039][1039],dis[1039][1039],h=1,t=0,mx[4]={1,0,-1,0},my[4]={0,1,0,-1},X,Y,sx,sy,dx,dy,x,y; bool check[1039][1039]={0}; bool inmap(ll x,ll y) { if(x<0 || y<0 || x>=X || y>=Y) { return 0; } return 1; } bool checkans(ll d) { if(dis[x][y]<d) { return 0; } memset(check,0,sizeof(check)); poi stp; ll a,b,c; stp.x=sx,stp.y=sy; h=1,t=0,que[++t]=stp; while(h<=t) { sum++; x=que[h].x,y=que[h].y; if(x==dx && y==dy) { return 1; } for(a=0;a<=3;a++) { x+=mx[a],y+=my[a]; if(inmap(x,y) && dis[x][y]>=d && !check[x][y]) { stp.x=x,stp.y=y; que[++t]=stp; check[x][y]=1; ansdis[x][y]=min(ansdis[x][y],ansdis[que[h].x][que[h].y]+1); } x-=mx[a],y-=my[a]; } h++; } return 0; } int main() { memset(dis,-1,sizeof(dis)); poi stp; ll n,le,ri,mi,a,b,c; scanf("%lld%lld%lld",&n,&X,&Y); scanf("%lld%lld%lld%lld",&sx,&sy,&dx,&dy); for(a=1;a<=n;a++) { scanf("%lld%lld",&stp.x,&stp.y); dis[stp.x][stp.y]=0; que[a]=stp; check[stp.x][stp.y]=1; } t=n; ri=0; while(h<=t) { x=que[h].x,y=que[h].y; for(a=0;a<=3;a++) { x+=mx[a],y+=my[a]; if(inmap(x,y) && dis[x][y]==-1) { stp.x=x,stp.y=y; que[++t]=stp; dis[stp.x][stp.y]=dis[que[h].x][que[h].y]+1; ri=max(ri,dis[stp.x][stp.y]); } x-=mx[a],y-=my[a]; } h++; } le=1; while(le+10<ri) { mi=(le+ri)>>1; if(checkans(mi)) { le=mi; } else { ri=mi-1; } } while(!checkans(ri)) { ri--; } for(a=0;a<X;a++) { for(b=0;b<Y;b++) { ansdis[a][b]=MAX_N; } } ansdis[sx][sy]=0; checkans(ri); printf("%lld %lld",ri,ansdis[dx][dy]); return 0; }
标签:限制 多少 格式 pen 行号 -- alt blog nbsp
原文地址:http://www.cnblogs.com/Sinogi/p/7086948.html