思路
因为题中说了曼哈顿距离 所以在遍历中 每走一步就是一个距离 就缩小了难度(业界良心。。)
因为题中说了曼哈顿距离 所以在遍历中 每走一步就是一个距离 就缩小了难度(业界良心。。)
又说要找最小最大距离。。
对于每一个点的预处理最小距离就是一定了
然后再找到那个最小最大距离
然后再来找步数
两个一定要分开找 不然时间上要t
因为找标准要logn次 就要清理logn次哈希表 如果把标准与步数一起更新 就要清理2*logn次哈希表
如果分开找 就只用清理logn+1次哈希表 就不会超时了。。。。
预处理
dis[i][j]表示i,j到最近的一个敌营的距离
如果暴力来 时间上o(n^3)1000*1000*1000t定了
就要机智一点,,
用bfs来实现 将所有敌营加到队列里 如果当前点的距离算过了
就continue 因为bfs先到的一定是最短距离
这样就只有o(n^2)
ok了。
找最小最大距离
找最小最大距离
这个肯定二分找了。。。不然呢、
在预处理的时候 记录下所有距离中的最大值
最小值就不管了 一定是0 (没想到军爷(不用在意这些细节)们居然可以直接穿过敌营 七进七出还战术撤退啊。。。O(∩_∩)O~)
最小值就不管了 一定是0 (没想到军爷(不用在意这些细节)们居然可以直接穿过敌营 七进七出还战术撤退啊。。。O(∩_∩)O~)
具体步骤见后代码
找到最小步数
裸bfs无压力
找到最小步数
裸bfs无压力
找到了二分出来的标准
就用标准来进行真实意义上的bfs
找到最短路
判断如果当前的距离在标准允许内就push 不然就continue
#include<iostream>/*预处理出i,j点到敌营 的最小值 先二分bfs找到一个离敌营最大值 在用标准bfs出最小步数*/
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int dx[5]={0,-1,1,0,0};
const int dy[5]={0,0,0,-1,1};
int hash[1000+10][1000+10];//最小step
int ste[1000+10][1000+10];//最少step
int maxn;
int l,r,mid;
struct edge
{
int v,u;
int step;
int mins;
}cs,ns,ans,res;
queue<edge>q;
int dis[1000+10][1000+10];
int t;
int n,x,y;
int stx,sty,enx,eny;
void readdata()
{
maxn=-1;
while(!q.empty())
q.pop();
cs.step=0;
cs.mins=0;
cs.u=0;
cs.v=0;
ans=cs;
memset(dis,0,sizeof(dis));
memset(ste,0,sizeof(ste));
scanf("%d%d%d",&n,&x,&y);
scanf("%d%d%d%d",&stx,&sty,&enx,&eny);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&cs.u,&cs.v);
dis[cs.u][cs.v]=-1;
q.push(cs);
}
}
void ready()
{
while(!q.empty())
{
cs=q.front();
q.pop();
for(int i=1;i<=4;i++)
{
ns=cs;
ns.u+=dx[i];
ns.v+=dy[i];
ns.step++;
if(ns.u<=x-1&&ns.u>=0)
if(ns.v<=y-1&&ns.v>=0)
if(!dis[ns.u][ns.v])
{
dis[ns.u][ns.v]=ns.step;
maxn=max(maxn,dis[ns.u][ns.v]);
q.push(ns);
}
}
}
while(!q.empty())
q.pop();
}
bool bfs_for_bz(int bz)
{
memset(hash,0,sizeof(hash)) ;
cs.u=stx;
cs.v=sty;
cs.mins=dis[stx][sty];
q.push(cs);
while(!q.empty())
{
cs=q.front();
q.pop();
for(int i=1;i<=4;i++)
{
ns=cs;
ns.u+=dx[i];
ns.v+=dy[i];
if(!(ns.u<=x-1&&ns.u>=0))
continue;
if(!(ns.v<=y-1&&ns.v>=0))
continue;
ns.mins=min(ns.mins,dis[ns.u][ns.v]);
if(dis[ns.u][ns.v]==-1)
ns.mins=0;
if(ns.mins<bz)
continue;
if(hash[ns.u][ns.v]==0)
{
if(ns.u==enx&&ns.v==eny)
{
while(!q.empty())
q.pop();
return true;
}
hash[ns.u][ns.v]=1;
q.push(ns);
}
}
}
return false;
}
int bfs_for_step(int bz)
{
cs.u=stx;
cs.v=sty;
cs.step=0;
q.push(cs);
while(!q.empty())
{
cs=q.front();
q.pop();
for(int i=1;i<=4;i++)
{
ns=cs;
ns.u+=dx[i];
ns.v+=dy[i];
ns.step++;
if(!(ns.u<=x-1&&ns.u>=0))
continue;
if(!(ns.v<=y-1&&ns.v>=0))
continue;
if(dis[ns.u][ns.v]==-1)
dis[ns.u][ns.v]=0;
if(dis[ns.u][ns.v]<bz)
continue;
if(ste[ns.u][ns.v]==0)
{
if(ns.u==enx&&ns.v==eny)
{
while(!q.empty())
q.pop();
return ns.step;
}
ste[ns.u][ns.v]=1;
q.push(ns);
}
}
}
}
int main()
{
scanf("%d",&t);
for(int tt=1;tt<=t;tt++)
{
readdata();
ready();
if(enx==stx&&eny==sty)
{
printf("%d %d\n",dis[enx][eny],0);
continue;
}
r=maxn;
l=0;
int cs=0;
while(l<=r)
{
mid=(l+r)/2;
if(bfs_for_bz(mid))
l=mid+1;
else r=mid-1;
}
if(mid==l)
{
printf("%d %d\n",mid-1,bfs_for_step(mid-1));
continue;
}
else
{
printf("%d %d\n",mid,bfs_for_step(mid));
continue;
}
}
}