2020ccpc威海B Labyrinth(思维+bfs扣关键点最短路)

13 篇文章 1 订阅

Due to the challenging problems, some of the contestants decide to escape from this contest. However, to prevent this from happening, the EVIL problem setters made a labyrinth at the stadium's exit. The labyrinth is made of an n×m grid, on which lie the entrance and the exit, and k black holes. Contestants who accidentally step into any black hole will fall into it and thus can never escape from the contest.

What's worse, the problem setters may also adjust the coordinates of the entrance and the exit. You, a poor contestant, who start from the entrance and wish to reach the exit without stepping into any of the black holes, can only move to one of the four adjacent cells in each step. You want to know, after each time the problem setters change the coordinates of the entrance and the exit, what's the minimum number of steps needed to reach the exit starting from the entrance?

Input Specification:

The first line of the input contains four integers n,m,k,q (1≤n,m≤200000,nm≤200000,0≤k≤42, 1≤q≤100000), denoting the number of rows, the number of columns, the number of black holes in the labyrinth, and the number of queries, respectively.

The following k lines contain the description of the black holes. Each of these lines contains two integers x,y (1≤x≤n,1≤y≤m), denoting the coordinates of a black hole. No two black holes are located at the same position.

The last q lines contain the description of the queries. Each of the q lines contains four integers x​s​​,y​s​​,x​t​​,y​t​​ (1≤x​s​​,x​t​​≤n,1≤y​s​​,y​t​​≤m), where (x​s​​,y​s​​) is the coordinates of the entrace and (x​t​​,y​t​​) is the exit.

Output Specification:

For each query, output a number in a line, denoting the minimum number of steps needed to reach the exit starting from the entrance. If it is impossible to reach the exit, output -1 instead. It should be considered impossible when the entrace or the exit coincides with a black hole.

Sample Input 1:

5 5 4 7
2 2
2 3
3 2
3 3
2 1 3 4
1 1 1 1
2 2 2 2
1 1 1 5
2 2 5 5
2 1 2 4
1 1 3 3

Sample Output 1:

6
0
-1
4
-1
5
-1

Sample Input 2:

2 3 2 1
1 2
2 1
1 1 2 3

Sample Output 2:

-1

Notes:

The plots for the labyrinth and the first query of the first sample data are shown below.

Screen Shot 2020-10-22 at 16.37.49.png


题意:图上有黑洞没法走,多次询问,求出两点之间的最短距离。

思路:

题目很关键的给了这么小的k,肯定从k出发

1.如果两个点之间没有黑洞,那么就是两点之间的曼哈顿距离。

2.如果有黑洞,那么最短路的路径经过过其中一个黑洞{上,下,左,右}的一个方向点。

那么预处理每个黑洞到图上所有点的最短距离,保存下来。询问的时候枚举所有黑洞的以各自四周为起点的到达给出两点的距离和,求最小值。

同时这个题卡空间,代码上用dis距离是否更新过来代替vis数组,dis数组也是动态分配的,用到再开。

注意一个黑洞的隔壁如果还是黑洞,这个dis空间是要开出来的,但不必bfs,不然的话在最后枚举最小值的时候是全范围枚举而没有空间就会段错误。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+100;
typedef int LL;
const int inf =0x3f3f3f3f;
set<pair<LL,LL>>st;
LL n,m,k,q;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
int *dis[50][4][maxn];///dis[id][pos][x][y];
///为了节省空间,用dis是否更新过来代替标记矩阵
vector<pair<LL,LL> >node;
struct Node{
  LL x,y,step;
};
void bfs()
{

    for(LL id=0;id<node.size();id++)///枚举所有黑洞作为起点
    {
        LL x,y;
        x=node[id].first;y=node[id].second;
        for(LL pos=0;pos<4;pos++)///枚举该黑洞的四周
        {
            LL xx=x+dx[pos];
            LL yy=y+dy[pos];
            if(xx<1||xx>n||yy<1||yy>m) continue;
            ///if(st.count({xx,yy})) continue;不能在这里判断
            for(LL p=1;p<=n;p++){
                dis[id][pos][p]=new int [m+5];
                for(LL o=1;o<=m;o++){
                    dis[id][pos][p][o]=inf;
                }
            }
            if(st.count({xx,yy})) continue;
            queue<Node>que;
            que.push({xx,yy,0});
            dis[id][pos][xx][yy]=0;
            while(!que.empty())
            {
                Node now=que.front();que.pop();
                for(LL p=0;p<4;p++){
                    LL tx=now.x+dx[p];LL ty=now.y+dy[p];LL tstep=now.step+1;
                    if(tx<1||tx>n||ty<1||ty>m) continue;
                    if(st.count({tx,ty})) continue;
                    if(dis[id][pos][tx][ty]!=inf) continue;
                    dis[id][pos][tx][ty]=tstep;
                    que.push({tx,ty,tstep});

                }
            }
        }
    }

}
bool check(LL x1,LL y1,LL x2,LL y2)
{
    if(x1>x2) swap(x1,x2);
    if(y1>y2) swap(y1,y2);
    for(LL i=0;i<k;i++){
        LL xx=node[i].first;
        LL yy=node[i].second;
        if(xx>=x1&&xx<=x2&&yy>=y1&&yy<=y2){
            return 1;
        }
    }
    return 0;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  cin>>n>>m>>k>>q;
  for(LL i=1;i<=k;i++){
    LL x,y;cin>>x>>y;
    node.push_back({x,y});
    st.insert({x,y});
  }
  bfs();
  ///cout<<"fuck"<<endl;
  while(q--)
  {
      LL x1,y1,x2,y2;
      cin>>x1>>y1>>x2>>y2;

      if(check(x1,y1,x2,y2)==0){
        cout<<abs(x2-x1)+abs(y2-y1)<<endl;
      }
      else{
        LL ans=0x3f3f3f3f;
        for(LL i=0;i<k;i++){

            for(int j=0;j<4;j++){
                int xx=node[i].first+dx[j];
                int yy=node[i].second+dy[j];
                if(xx<1||xx>n||yy<1||yy>m) continue;
                ans=min(ans,dis[i][j][x1][y1]+dis[i][j][x2][y2]);

            }
        }
        if(ans==inf)cout<<"-1"<<endl;
        else cout<<ans<<endl;
      }
  }
  return 0;
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值