题目描述
小明公司的办公区有一条长长的走廊,由 NN 个方格区域组成,如下图所示。
走廊内部署了 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
【思路及代码】
本题属于二分算法题目,求最短的花费时间,所以可以对花费的时间使用二分来求解,最短的时间就是每个位置都已打扫完0,最长就是只有一台机器需要打扫n个地点且要回到原点,所以花费时间最长为2*n.
需要找最小值,所以采用如下的二分模板
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid))//符合条件
r=mid;//接着向左寻找最小值
else l=mid+1;
}
使用last记录需要打扫的最后位置,具体代码如下
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int n,st[N],k;
bool check(int mid)
{
//if(mid<(a[1]-1)*2||mid<(n-a[k])*2)
// return false;
int last=1;
for(int i=1;i<=k;i++)
{
if(a[i]>last)//向左扫
{
if(a[i]-last>mid/2)
return false;
else if(a[i]-last==mid/2)
last=a[i]+1;
else if(a[i]-last<mid/2)
last=a[i]+(mid/2-a[i]+last)+1;
}
else if(a[i]<=last)//向右扫
{
last=max(last,a[i]+mid/2+1);
}
/*
if(a[i]-last>mid/2)
return false;
if((a[i]-last)==mid/2) last=a[i];
else if((a[i]-last)<mid/2)
last=a[i]+(mid/2-a[i]+last);
*/
}
if(last>n) return true;
else
return false;
}
int main()
{
cin>>n>>k;
for(int i=1;i<=k;i++)
{
cin>>a[i];
}
sort(a+1,a+1+k);//按照所在位置的先后位置排序
int l=0,r=2*n;//最长用的时间
while(l<r)
{
int mid=(l+r)/2;
if(check(mid))
r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}