2020CCPC威海B Labyrinth(new动态开内存+bfs)

银牌题,但是有点卡人心态。 time :5s  mel :1024mb 

  题意:给定k<=42个黑洞(黑洞不能经过),n*m<=200000的矩阵,q<=100000次询问,给定x1,y1,x2,y2,问最短路,不存在则-1.

  可以说是思路一眼题啊,如果两个点之间(也就是两矩阵之间)没有黑洞的话,直接曼哈顿距离即可,而且这样用矩阵前缀和即可处理。如果有黑洞的话,一定是从所有黑洞相邻的点转移过去(两个距离之和取最小),所以我们要记一个dis的三维数组,大小为k*4*n*m,最大4e7左右,所以这个数组要定义在外面,所以就用到了int ***dis +new 动态开内存,每个dis 数组可以用bfs求得。

口胡一下:如果把二维矩阵转为一维2e5,然后搞一个坐标对应函数也可以吧~~~

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
typedef  long long ll;
using namespace std;
#define rep(i,j,n) for(ll i=j;i<=n;i++)
typedef unsigned long long ull;
typedef unsigned short us;
const int INF= 1e9+7;
const ll maxn = 2e6+7;
const ll maxx = 2e6+7;
const ll mod= 998244353;
inline bool read(int &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
int n,m,p,k,q;
int dx[5]={0,0,-1,1};
int dy[5]={-1,1,0,0};

int x[maxx],y[maxx];
int ***dis;
int main(){
    ll Q;
    cin>>n>>m>>k>>Q;
    int a[n+5][m+5];
    int sum[n+5][m+5];
    memset(a,0,sizeof(a));
    memset(sum,0,sizeof(sum));
    bool vis[n+5][m+5];
    rep(i,1,k)
    {
        read(x[i]);read(y[i]);
        a[x[i]][y[i]]=1;
    }
    rep(i,1,n)
    rep(j,1,m)
    {
        sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    }
    ll geshu=0;
    memset(vis,0,sizeof(vis));
    rep(i,1,k)
    {
        rep(j,0,3)
        {
            int px=x[i]+dx[j];
            int py=y[i]+dy[j];
           // printf("%lld %lld\n",px,py);
            if(a[px][py]==0&&px>=1&&px<=n&&py>=1&&py<=m )
            {
                geshu++;
            }
        }
    }

    dis= new int **[k*4-2];

    rep(i,1,geshu+2)
    {
        dis[i]=new int*[n+5];
        rep(j,1,n)
        dis[i][j]=new int[m+5];
    }

    rep(i,1,geshu)
    rep(j,1,n)
    rep(k,1,m) dis[i][j][k]=-1;

    int cnt=0;
    rep(i,1,k)
    {
        rep(j,0,3)
        {
            memset(vis,0,sizeof(vis));
            int px=x[i]+dx[j];
            int py=y[i]+dy[j];
           // printf("%lld %lld\n",px,py);
            if(a[px][py]==0&&px>=1&&px<=n&&py>=1&&py<=m)
            {
                ++cnt;
                dis[cnt][px][py]=0;
                queue<pair<int,int> >q;
                q.push(make_pair(px,py));
                vis[px][py]=1;
                while(!q.empty())
                {
                    int x=q.front().first;
                    int y=q.front().second;
                    int juli=dis[cnt][x][y];
                    //printf("%d %d\n",x,y);
                    q.pop();
                    rep(l,0,3)
                    {
                        ll qx=x+dx[l];
                        ll qy=y+dy[l];
                        if(!vis[qx][qy]&&a[qx][qy]==0&&qx>=1&&qx<=n&&qy>=1&&qy<=m)
                        {
                            dis[cnt][qx][qy]=juli+1;
                            vis[qx][qy]=1;
                            q.push(make_pair(qx,qy));
                        }
                    }
                }

            }
        }
    }
    rep(i,1,Q)
    {
        int x1,y1,x2,y2;
        read(x1);read(y1);read(x2);read(y2);
        int p1=min(x1,x2);
        int p3=min(y1,y2);
        int p2=max(x1,x2);
        int p4=max(y1,y2);
       // cout<<sum[p2][p4]-sum[p1-1][p4]-sum[p2][p3-1]+sum[p1-1][p3-1]<<endl;
        if(a[x1][y1]==1||a[x2][y2]==1) {
       // printf("wdqqwd\n");
            printf("-1\n");
        }
        else if(sum[p2][p4]-sum[p1-1][p4]-sum[p2][p3-1]+sum[p1-1][p3-1] == 0)
        {
            int ans=y1-y2;
            printf("%d\n",abs(x1-x2)+abs(ans));
        }
        else
        {
            int minl=INF;
            rep(i,1,cnt)
            {
                if(dis[i][x1][y1]!=-1&&dis[i][x2][y2]!=-1)
                {
                    minl=min(minl,dis[i][x1][y1]+dis[i][x2][y2]);
                }
            }
            if(minl==INF) printf("-1\n");
            else printf("%d\n",minl);
        }
    }
    return 0;
}
/***
5 5 8 100
2 2
2 3
2 4
3 2
3 4
4 2
4 3
4 4
***/


 

B Labyrinth

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

Figure 1: Plots for sample test data

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值