教主的花园

16 篇文章 0 订阅

Description

【问题背景】

  LHX教主最近总困扰于前来膜拜他的人太多了,所以他给他的花园加上了一道屏障。

【问题描述】

  可以把教主的花园附近区域抽像成一个正方形网格组成的网络,每个网格都对应了一个坐标(均为整数,有可能为负),若两个网格(x1, y1),(x2, y2)有|x1 – x2| + |y1 – y2| = 1,则说这两个网格是相邻的,否则不是相邻的。
  教主在y = 0处整条直线上的网格设置了一道屏障,即所有坐标为(x, 0)的网格。当然,他还要解决他自己与内部人员的进出问题,这样教主设置了N个入口a1, a2, …, aN可供进出,即对于y = 0上的所有网格,只有 (a1, 0),(a2, 0), ……, (aN, 0) 可以通过,之外的所有纵坐标为0的网格均不能通过,而对于(x, y)有y不为0的网格可以认为是随意通过的。
  现在教主想知道,给定M个点对(x1, y1),(x2, y2),并且这些点均不在屏障上,询问从一个点走到另一个点最短距离是多少,每次只能从一个格子走到相邻的格子。

Input

  输入的第1行为一个正整数N,为屏障上入口的个数。
  第2行有N个整数,a1, a2, …, aN,之间用空格隔开,为这N个入口的横坐标。
  第3行为一个正整数M,表示了M个询问。
  接下来M行,每行4个整数x1, y1, x2, y2,有y1与y2均不等于0,表示了一个询问从(x1, y1)到(x2, y2)的最短路。

Output

  输出共包含m行,第i行对于第i个询问输出从(x1, y1)到(x2, y2)的最短路距离是多少。

Sample Input

2
2 -1
2
0 1 0 -1
1 1 2 2

Sample Output

4
2

Data Constraint

Hint

【数据规模】

  对于20%的数据,有n,m≤10,ai,xi,yi绝对值不超过100;
  对于40%的数据,有n,m≤100,ai,xi,yi绝对值不超过1000;
  对于60%的数据,有n,m≤1000,ai,xi,yi绝对值不超过100000;
  对于100%的数据,有n,m≤100000,ai,xi,yi绝对值不超过100000000。

思路

还是比较水的。。。但是我初评WA了
两种情况:
1. 两个点分布在屏障同一侧,则直接输出dist。
2. 两个点分布在异侧,我们就二分出口,若mid往某个方向移动,使得dist

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[111111],x1,x2,y1,y2,door,n,m,ans;
int cmp(int x,int y)
{
    return x<y;
}
int abs(int x)
{
    if(x<0) return -x;else return x;
}
int dist(int p1,int q1,int p2,int q2)
{
    return(abs(p1-p2)+abs(q1-q2));
}
void fin(int l,int r,int ql,int qr)
{
    if(l>=r) {door=a[l];return;}
    int mid=(l+r)>>1;
    if(ql<=a[mid] && qr>=a[mid]){door=a[mid];return;}else
    ans=dist(x1,y1,a[mid],0)+dist(a[mid],0,x2,y2);
    if(mid<n && dist(x1,y1,a[mid+1],0)+dist(a[mid+1],0,x2,y2)<ans) fin(mid+1,r,ql,qr);else
    if(mid>1 && dist(x1,y1,a[mid-1],0)+dist(a[mid-1],0,x2,y2)<ans) fin(l,mid-1,ql,qr);else
    {
        door=a[mid]; return;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1,cmp);
    scanf("%d",&m);
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        if(y1>y2)
        {
            int t=x1;x1=x2;x2=t;t=y1;y1=y2;y2=t;
        }
        if(x1==x2 && y1==y2) {printf("0"); return 0;}
        if(y1<=0 && y2>=0)
        {
            ans=2147483647;
            fin(1,n,x1,x2);
            printf("%d\n",dist(x1,y1,door,0)+dist(door,0,x2,y2));
        }else
        {
            printf("%d\n",dist(x1,y1,x2,y2));
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值