题目描述
小张公司的办公区有一条长长的走廊,由 N 个方格区域组成,如下图所示。
走廊内部署了 K 台扫地机器人,其中第 i 台在第 Ai 个方格区域中。已知扫地机器人每分钟可以移动到左右相邻的方格中,并将该区域清扫干净。
请你编写一个程序,计算每台机器人的清扫路线,使得
-
它们最终都返回出发方格,
-
每个方格区域都至少被清扫一遍,
-
从机器人开始行动到最后一台机器人归位花费的时间最少。
注意多台机器人可以同时清扫同一方块区域,它们不会互相影响。
输出最少花费的时间。 在上图所示的例子中,最少花费时间是 6。第一台路线:2-1-2-3-4-3-2,清 扫了 1、2、3、4 号区域。第二台路线 5-6-7-6-5,清扫了 5、6、7。第三台路线 10-9-8-9-10,清扫了 8、9 和 10。
输入描述
第一行包含两个整数 N,K。
接下来 K 行,每行一个整数 Ai。
其中,1≤K<N≤105,1≤Ai≤N。
输出描述
输出一个整数表示答案。
输入输出样例
输入
10 3
5
2
10
输出
6
思路:
题目要求最少花费时间。由于每个机器人的工作时间可能不同,那么这些机器人各自的花费时间中的最大值(设为 t )的就是本题要求的答案,我们需要做的是使得 t 最小。将最大花费时间(t)最小化,显然我们需要使用二分求解。
我们假设某个机器人需要清扫 a,b,c,d 四个格子,因为这个机器人清扫完还需要回到最初始的位置,所以无论这个机器人初始位置在什么地方,其清扫路径的本质都是重复两次 a 到 b,b 到 c,c 到 d 的过程,花费时间为 6,由此,我们假设某个机器人清扫的格子范围为 l, 那么这个机器人花费的时间为 (l−1)×2。所以我们只需要对机器人清扫的范围(l)进行二分即可,最后的答案为 t=(l−1)×2。
显然当每个机器人清扫的范围大小相同时,花费时间最小。我们可以对清扫范围进行二分,然后验证其答案的正确性即可,判断条件是清扫范围可以使得每个格子都能够扫到。
参考代码:
n,k=map(int,input().split())
a=[0] #这里加个0是因为下面从1开始
for i in range(k):
a.append(int(input()))
a.sort() #从小到大排序
def check(d): # 检查每一个清理距离是否能将走廊清理完成
len=0 #覆盖长度,从最左端开始一直到最右端
for i in range(1,k+1):
if len+d>=a[i]:
if len>a[i]:
len=a[i]+d-1 #这里减1是因为自己本身也需要清理
else: #否则直接就是当前长度+d
len+=d
else:
return False
return len>=n
l,r=1,n #最短是1,最长是n
while l<r: #二分查找计算清扫范围
mid=(l+r)//2
if check(mid):
r=mid
else:
l=mid+1
print((l-1)*2)