一条直线走廊上有n个人和k把钥匙。每个人都想去也这条线上处于位置p的办公室。要做到这一点,他们需要拿到钥匙,拿着钥匙去办公室。一旦钥匙被人拿走了,其他人就拿不到了。你要确定所有人带着钥匙到达办公室所需的最短时间。假设人们每秒钟移动一个单位距离。如果两个人同时拿到钥匙,只有一个人可以拿钥匙并且不能把钥匙给别人。
输入
第一行包含三个整数n,k和p(1≤n≤k≤2000,1≤p≤10^9),分别表示人数,钥匙数和办公地点。
第二行包含n个不同的整数a1,a2,…,an(1≤ai≤10^9),表示人的初始位置。这些位置是按任意顺序给出的。
第三行包含k个不同的整数b1,b2,…,bk(1≤bj≤10^9),表示钥匙的位置。这些位置是按任意顺序给出的。
注意,同一位置上不能有多于一个人或多于一个钥匙。一个人和一把钥匙可以定位在同一点上。
输出
输出所有的n个人带着钥匙到达办公室所需的最短时间(秒)。
输入样例 1
2 4 50 20 100 60 10 40 80
输出样例 1
50
输入样例 2
1 2 10 11 15 7
输出样例 2
7
样例解释:
在第一个例子中,位于20的人应该拿着位于40的钥匙,带着它去位于50的办公室。他只花了30秒。位于100的人可以拿着位于80的钥匙去办公室。他花了50秒。因此,50秒后,每个人都拿着钥匙进入办公室。
思路:将人和钥匙从小到大排序。每个人花费的时间=人与钥匙的距离+钥匙距离办公室的距离
画图可知,第一个人从第一个钥匙开始找,如果有某个钥匙拿完后时间小于mid,说明可。然后第二个人紧接上上一个人拿到钥匙的地方继续往后找钥匙。【因为前面的钥匙距离第一个人是比较近的,第一个人拿了都不满足时间,距离远的下一个人更不可能符合】,如果人数超过了n个,说明当前时间是合适的,接下来去寻找比它小的还有没有合适的了。
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long long n,k,p;
long long a[10000];
long long b[10000];
bool check(long long mid){
int cnt=1;
for(int i=1;i<=k;i++){
if(abs(a[cnt]-b[i])+abs(p-b[i])<=mid){
cnt++;
}
if(cnt>n)
return true;
}
return false;
}
int main(){
cin>>n>>k>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=k;i++){
cin>>b[i];
}
sort(a+1,a+1+n);
sort(b+1,b+1+k);
long long left=0,right=2*1000000000,ans;
while(left<=right){
long long mid=(left+right)/2;
if(check(mid)){
ans=mid;
right=mid-1;
}
else{
left=mid+1;
}
}
cout<<ans;
return 0;
}