【CF413E】 Maze 2D

题目

题目描述
The last product of the R2 company in the 2D games’ field is a new revolutionary algorithm of searching for the shortest path in a 2×n2×n maze.

Imagine a maze that looks like a 2×n2×n rectangle, divided into unit squares. Each unit square is either an empty cell or an obstacle. In one unit of time, a person can move from an empty cell of the maze to any side-adjacent empty cell. The shortest path problem is formulated as follows. Given two free maze cells, you need to determine the minimum time required to go from one cell to the other.

Unfortunately, the developed algorithm works well for only one request for finding the shortest path, in practice such requests occur quite often. You, as the chief R2 programmer, are commissioned to optimize the algorithm to find the shortest path. Write a program that will effectively respond to multiple requests to find the shortest path in a 2×n2×n maze.

输入格式
The first line contains two integers, nn and mm (1<=n<=2·10^{5}; 1<=m<=2·10^{5})(1<=n<=2⋅10
5
; 1<=m<=2⋅10
5
) — the width of the maze and the number of queries, correspondingly. Next two lines contain the maze. Each line contains nn characters, each character equals either ‘.’ (empty cell), or ‘X’ (obstacle).

Each of the next mm lines contains two integers v_{i}v
i

and u_{i}u
i

(1<=v_{i},u_{i}<=2n)(1<=v
i

,u
i

<=2n) — the description of the ii -th request. Numbers v_{i}v
i

, u_{i}u
i

mean that you need to print the value of the shortest path from the cell of the maze number v_{i}v
i

to the cell number u_{i}u
i

. We assume that the cells of the first line of the maze are numbered from 11 to nn , from left to right, and the cells of the second line are numbered from n+1n+1 to 2n2n from left to right. It is guaranteed that both given cells are empty.

输出格式
Print mm lines. In the ii -th line print the answer to the ii -th request — either the size of the shortest path or -1, if we can’t reach the second cell from the first one.

题意翻译
给一个2*n 的地图,有一些X不能走,没有修改,问一个点到另一个点的最短距离

输入输出样例
输入 #1复制
4 7
.X…
…X
5 1
1 3
7 7
1 4
6 1
4 7
5 7
输出 #1复制
1
4
0
5
2
2
2
输入 #2复制
10 3
X…X…X…
…X…X…X
11 7
7 18
18 10
输出 #2复制
9
-1
3

思路

我们需要做两件事情

  1. 维护一个[l,r]区间中四个角相互之间的最短路
  2. 查询
    于是乎,线段树!

代码

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int mmp[3][200001];

int n;
int ans;
char c[300001];
struct data{
	int d1,d2,d3,d4;
};
struct tree{
    int l, r;
    data d;
}t[4*200001];
data merge(data a,data b)
{
    data s;
    s.d1=min(inf,min(a.d1+b.d1,a.d2+b.d3)+1);
    s.d2=min(inf,min(a.d1+b.d2,a.d2+b.d4)+1);
    s.d3=min(inf,min(a.d3+b.d1,a.d4+b.d3)+1);
    s.d4=min(inf,min(a.d3+b.d2,a.d4+b.d4)+1);
    return s;
}
void init(int s,int l,int r)
{
    t[s].l=l,t[s].r=r;
    if(l==r){
        t[s].d.d1=t[s].d.d2=t[s].d.d3=t[s].d.d4=inf;
        if(mmp[1][l]) t[s].d.d1=0;
        if(mmp[2][l]) t[s].d.d4=0;
        if(mmp[1][l]&&mmp[2][l]) t[s].d.d2=t[s].d.d3=1;
        return ;
    }
    int m=(l+r)/2;
    init(2*s,l,m);
    init(2*s+1,m+1,r);
    t[s].d=merge(t[2*s].d,t[2*s+1].d);
}
data q(int s,int x,int y)
{
    int l=t[s].l,r=t[s].r;
    if(x==l&&y==r) return t[s].d;
    int m=(l+r)/2;
    if(m>=y) return q(2*s,x,y);
    else if(m<x) return q(2*s+1,x,y);
    else
        return merge(q(2*s,x,m),q(2*s+1,m+1,y));
}
void ask(int x,int y)
{
    int a=(x-1)%n+1,b=(y-1)%n+1;
    if(a>b){
        swap(x,y);
        swap(a,b);
    }
    data s=q(1,a,b);
    if(x<=n&&y<=n) ans=s.d1;
    if(x<=n&&y>n) ans=s.d2;
    if(x>n&&y<=n) ans=s.d3;
    if(x>n&&y>n) ans=s.d4;
}
int main()
{
    int m;
    cin>>n>>m;
    int i,j;
    for(i=1; i<=2; i++)
    {
    	scanf("%s",c);
    	for(j=1;j<=n;j++)
    	   if(c[j-1]=='.') mmp[i][j]=1;
    }
    init(1,1,n);
    int x,y;
    for(i=1; i<=m; i++)
	{
        cin>>x>>y;
        ask(x,y);
        if(ans<inf) cout<<ans<<endl;
        else cout<<"-1\n";
    }
	return (0-0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值