A. Office Keys(贪心+二分枚举)

https://codeforces.com/problemset/problem/830/A

题意翻译

在一条直线上有n人和k个钥匙。每个人都想到达位于线路上的办公室。要做到这一点,他需要到一个有钥匙的点上,拿到钥匙然后去办公室。

  1. 一旦有人拿走钥匙,任何人都不能拿走钥匙。
  2. 人们每1秒移动一个单位距离。 您需要确定所有人用钥匙到达办公室的最短时间。 如果两个人同时拿到钥匙,他们中只有一个可以拿钥匙。而一个人只能通过那个点而不能获取钥匙。 翻译贡献者UID:46780

输入输出样例

输入 #1复制

2 4 50
20 100
60 10 40 80

输出 #1复制

50

输入 #2复制

1 2 10
11
15 7

输出 #2复制

7

说明/提示

In the first example the person located at point 2020 should take the key located at point 4040 and go with it to the office located at point 5050 . He spends 3030 seconds. The person located at point 100100 can take the key located at point 8080 and go to the office with it. He spends 5050 seconds. Thus, after 5050 seconds everybody is in office with keys.


思路:首先看到最小化最大值,二分无误。

然后人到出口距离=abs(a[i]-b[j])+abs(p-b[j])。即人到钥匙的距离加上钥匙到出口距离。

check的时候要考虑贪心,对人到钥匙的距离和钥匙到出口的距离进行sort从小到大。

前一个人去的钥匙位置一定在后一个人取得钥匙前面,否则产生交叉肯定多浪费时间。

这里的交叉可以画两个钥匙两人,出口,出口放中间,右边,左边的时候去感受。

主要还是贪心的想法比较难。以后遇到贪心尝试从小样例去构造,猜想。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e3+100;
typedef long long LL;
LL a[maxn],b[maxn];
LL n,k,p;
bool check(LL x)
{
	LL i=1;
	for(LL j=1;j<=k;j++){
		if(abs(a[i]-b[j])+abs(p-b[j])<=x){
			i++;
		}
		if(i>n) return true; 
	}
	return false;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  cin>>n>>k>>p;
  for(LL i=1;i<=n;i++) cin>>a[i];
  for(LL i=1;i<=k;i++) cin>>b[i];
  sort(a+1,a+1+n);sort(b+1,b+1+k);
  LL l=0;LL r=2e9+100;
  while(l<r)
  {
  	LL mid=(l+r)/2;
  	if(check(mid)) r=mid;
  	else l=mid+1;
  }
  cout<<l<<endl;
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108513552