题目
In the year of 30
XX
participants of some world programming championship live in a single large hotel. The hotel has n floors. Each floor has m sections with a single corridor connecting all of them. The sections are enumerated from
1
to
The guests can walk along the corridor on each floor, use stairs and elevators. Each stairs or elevator occupies all sections
(1,x)
,
(2,x)
, …,
(n,x)
for some
x
between
You are to process q queries. Each query is a question “what is the minimum time needed to go from a room in section
Input
The first line contains five integers
n
,
The second line contains cl integers
The third line contains ce integers e1 ,…, ece in increasing order, denoting the elevators positions in the same format. It is guaranteed that all integers li and ei are distinct.
The fourth line contains a single integer
q
(1 ≤
The next
q
lines describe queries. Each of these lines contains four integers
Output
Print q integers, one per line — the answers for the queries.
Example
Input |
---|
5 6 1 1 3 2 5 3 1 1 5 6 1 3 5 4 3 3 5 3 |
Output |
7 5 4 |
Note
In the first query the optimal way is to go to the elevator in the 5-th section in four time units, use it to go to the fifth floor in two time units and go to the destination in one more time unit.
In the second query it is still optimal to use the elevator, but in the third query it is better to use the stairs in the section 2.
分析
题意:给一个酒店,有
分析:楼层之间最优的移动方案一定是下面四个中的一个
- 乘y1左边最近的电梯
- 乘y1右边最近的电梯
- 走y1左边最近的楼梯
- 走y1右边最近的楼梯
由于电梯可能在很远的位置,所以走楼梯的情况也必须考虑。
所以,把四个方案的代价计算出来取最优即可,由于电梯和楼梯的个数都在1e5,考虑用二分查找离y1最近的电梯/楼梯所在的位置。因为左边最近和右边最近的位置是相邻的,所以用二分查找一次就可以完成。
注意:需要特判起点和终点在同一层楼的情况;以及电梯/楼梯没有的时候,不能自己生成一个电梯/楼梯来使用(划掉)。
代码
#include<stdio.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mabs(x) ((x)>0?(x):(0-(x)))
#define N_max 100005
/*
*n层楼
*每层楼m个房间,按1~m编号,相同编号的水平位置相同
*把房间表示为(i, j),意思是i层楼的j房间
*在走廊上走,走楼梯或坐电梯
*每个x的楼梯或电梯占有了所有(i, x)
*房间之间或层之间走动1花费1,坐电梯走动v花费1
*查询:从(x1, y1)到(x2, y2)
*/
int n, m, cl, ce, v, q;
int flr[100005], elv[100005];
//二分查找一次完成对左右电梯/楼梯的查找
void bins(int a[], int n, int x,int *_l,int *_r) {
int l = -1, r = n, m;
//二分求l,是左边最近的位置
while (l + 1 < r) {
m = (l + r) / 2;
if (a[m] <= x)l = m;
else r = m;
}
if (l == -1)//没有在x左边的电梯/楼梯,选一个最左边的来代替
l = 0;
//求r,是与l相邻的位置
if (a[l] == x)//如果l是x的位置,那么使用该电梯/楼梯是最优的
r = l;
//没有在x右边的电梯/楼梯,选一个最右边的来代替
else r = (l + 1 )>= n ? n - 1 : l + 1;
//传递结果
*_l=l;*_r=r;
}
int sol(int x1, int y1, int x2, int y2) {
int l, r;
int costf, coste;
int cost1, cost2, cost3;
//同一层楼特判
if (x1 == x2)
return mabs(y1 - y2);
//走左右最近的楼梯
bins(flr, cl, y1,&l,&r);
costf = min(mabs(y1 - flr[l]) + mabs(x2 - x1) + mabs(y2 - flr[l]),
mabs(y1 - flr[r]) + mabs(x2 - x1) + mabs(y2 - flr[r]));
//左右最近的电梯
bins(elv, ce, y1,&l,&r);
coste = min(mabs(y1 - elv[l]) + mabs(x2 - x1) / v + (mabs(x2 - x1) % v != 0) + mabs(y2 - elv[l]),
mabs(y1 - elv[r]) + mabs(x2 - x1) / v + (mabs(x2 - x1) % v != 0) + mabs(y2 - elv[r]));
//该解法没有考虑电梯/楼梯没有的情况,在最后判断
if (cl == 0)return coste;
else if (ce == 0)return costf;
return min(costf, coste);
}
int main() {
int x1, y1, x2, y2;
scanf("%d %d %d %d %d", &n, &m, &cl, &ce, &v);
for (int i = 0; i < cl; ++i)
scanf("%d", &flr[i]);
for (int i = 0; i < ce; ++i)
scanf("%d", &elv[i]);
scanf("%d", &q);
int ans;
for (int i = 0; i < q; ++i) {
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
ans = sol(x1, y1, x2, y2);
printf("%d\n", ans);
}
}