写在前面:
这题赛时就过了二十多个人感觉还是榜歪了,完全没有到金牌题的水平,算是一道纯思维题吧,只需要简单的bfs,而且赛中也有一些铜牌区的队伍能过,所以还是要敢于开题,说不定就能写呢
题意:
给了一个n行m列的地图,有k个障碍物,q次询问每次给出两个点的坐标问两点间的最短路径
范围:
(
n
,
m
<
=
200000
)
,
(
n
∗
m
<
=
200000
)
,
(
k
<
=
42
)
,
(
q
<
=
100000
)
(n,m<=200000),(n*m<=200000),(k<=42),(q<=100000)
(n,m<=200000),(n∗m<=200000),(k<=42),(q<=100000)
知识点:
思维,
b
f
s
bfs
bfs
题解:
求两点之间的最短距离,两种情况
1:距离为最短距离
2:距离为非最短
若结果为2,则一定经过至少一个障碍物的相邻点
如图:
图示起点到终点的一种最短路径经过1好点的上方
考虑求出所有障碍物相邻点x到其它所有点y的最短距离d[x][y]
情况2的结果为
m
i
n
1
=
m
i
n
(
m
i
n
1
,
d
[
x
]
[
起点
]
+
d
[
x
]
[
终点
]
)
min1=min(min1,d[x][起点]+d[x][终点])
min1=min(min1,d[x][起点]+d[x][终点])
判断起点到终点是情况1还是2即可
将起点到终点连接成一个矩形,若矩形内没有障碍物则为情况1,若矩形内有障碍物则继续分类
3、有障碍物且起点到终点距离为最短
4、有障碍物且起点到终点距离为非最短
若为情况3
如图:
一定有一条最短路径经过至少一个障碍物相邻点,情况3结果为
m
i
n
1
min1
min1
若为情况4则与情况2对应,结果为 m i n 1 min1 min1
综上所述:若起点与终点连接成的矩形内没有障碍物则结果为最短距离,若有障碍物则结果为 m i n 1 min1 min1
复杂度分析:
判断矩形内是否有障碍物用二维前缀和即可
所有障碍物相邻点跑一遍
b
f
s
bfs
bfs +每次询问时间
O
(
4
k
∗
(
n
m
+
q
)
)
O(4k*(nm+q))
O(4k∗(nm+q))
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1e9+7;
const int N=2e5+5;
vector<int>w[170][200002];
vector<bool>bj[200002],bj1[200002];
vector<int>s[200002],sum[200002];
struct duqi{
int x,y,k;
};
duqi q[N];
duqi qq[200];
duqi qq1[50];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
int main()
{
int i,j,l,n,m,t,k,l1,r,r1,mid,g,max1,i1,w2,x,h,y,v,x0,y0,p1,g1,p,min1;
g=0;g1=1e9;
scanf("%d%d%d%d",&n,&m,&k,&t);
for(i=0;i<=n+1;i++){
for(j=0;j<=m+1;j++)bj[i].push_back(g),s[i].push_back(g),bj1[i].push_back(g),sum[i].push_back(g);
}
p=0;p1=0;
for(i=1;i<=k;i++){
scanf("%d%d",&x,&y);qq1[++p1].x=x,qq1[p1].y=y;
s[x][y]=1;
}
for(i=1;i<=k;i++)
for(j=0;j<4;j++){
x0=qq1[i].x+dx[j];y0=qq1[i].y+dy[j];
if(bj[x0][y0]==0&&x0>=1&&x0<=n&&y0>=1&&y0<=m&&s[x0][y0]==0)qq[++p].x=x0,qq[p].y=y0,bj[x0][y0]=1;
}
for(i1=1;i1<=p;i1++)
for(i=0;i<=n+1;i++)
for(j=0;j<=m+1;j++)w[i1][i].push_back(g1);
for(i1=1;i1<=p;i1++){
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)bj1[i][j]=0;
q[1]=qq[i1];q[1].k=0;bj1[qq[i1].x][qq[i1].y]=1;
for(i=1,j=1;i<=j;i++){
w[i1][q[i].x][q[i].y]=q[i].k;
for(l=0;l<4;l++){
x0=q[i].x+dx[l];y0=q[i].y+dy[l];
if(bj1[x0][y0]==0&&x0>=1&&x0<=n&&y0>=1&&y0<=m&&s[x0][y0]==0){
q[++j].x=x0;q[j].y=y0;q[j].k=q[i].k+1;bj1[x0][y0]=1;
}
}
}
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+s[i][j];
while(t--){
scanf("%d%d%d%d",&x,&y,&x0,&y0);
min1=1e9;
for(i=1;i<=p;i++){
min1=min(min1,w[i][x][y]+w[i][x0][y0]);
}
k=max(x,x0);x=min(x,x0);x0=k;
k=max(y,y0);y=min(y,y0);y0=k;
if(sum[x0][y0]-sum[x0][y-1]-sum[x-1][y0]+sum[x-1][y-1]==0)printf("%d\n",x0-x+y0-y);
else
if(min1==1e9)printf("-1\n");
else
printf("%d\n",min1);
}
}