题目描述

小明公司的办公区有一条长长的走廊,由 NN 个方格区域组成,如下图所示。

扫地机器人(蓝桥杯C/C++)

走廊内部署了 KK 台扫地机器人,其中第 ii 台在第 A_iAi​ 个方格区域中。已知扫地机器人每分钟可以移动到左右相邻的方格中,并将该区域清扫干净。

请你编写一个程序,计算每台机器人的清扫路线,使得

  1. 它们最终都返回出发方格,

  2. 每个方格区域都至少被清扫一遍,

  3. 从机器人开始行动到最后一台机器人归位花费的时间最少。

注意多台机器人可以同时清扫同一方块区域,它们不会互相影响。

输出最少花费的时间。 在上图所示的例子中,最少花费时间是 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​。

扫地机器人(蓝桥杯C/C++)

输出描述

输出一个整数表示答案。

扫地机器人(蓝桥杯C/C++)

我们不妨按照这样的思路解题:

我们引入这样的例子:

比如给一根绳,围成一个矩形,求在长和宽为多少时矩形面积最大

那么,可求得当长和宽相等时矩形面积最大,长和宽之间的差距为0

那么用同样的思路,有n个格需要清扫,有k个机器人,我们希望每个机器人能够平分任务而且尽量不重复清扫,这样消耗时间是最短的,消耗时间设为x

所以,这里用二分查找计算出最小值

剩下的思路不好表达,不妨结合代码来说

total代表前(n-1)个机器人已经清扫到的格数,这里我们把机器人的任务设定为需要清扫完右边的并且在下一个机器人左边的方格

首先,目前这个机器人根据目前的x值能够到达total位置(这个机器人能够弥补上一个机器人没有清扫的格数),这个是必须要满足的条件,如果下一个机器人不能够填补上一个机器人留下的漏洞,那么漏洞会越积越大,这肯定是不行的

然后,满足了这个条件后,就需要优中选优,这里我们分为两种情况讨论:

1.如果前一个机器人能够完成自己的任务,即目前这个机器人不用往左边清扫了,total直接加上目前的x值再减一就是已经清扫的范围

2.如果前一个机器人不能完成自己的任务,那么需要先完成前一个机器人剩下的任务,然后再开始自己的工作

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int n,m;
int robot_list[maxn];
bool check(int x)
{
	int total=0;
	for(int i=0;i<m;i++)
	{
		if(robot_list[i]-x<=total)//能够到达total位置,弥补前面一个机器人留的未清扫区域 
		{
			if(robot_list[i]<=total) total=robot_list[i]+x-1;
			else total+=x;//左边没扫完  
		}
		else return false; //不能够到达total位置,不能弥补前面一个机器人留的未清扫区域,直接失败 
	}
	return total>=n;//这种情况下才成立,返回true 
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		cin>>robot_list[i];
	}
	sort(robot_list,robot_list+m);//排序
	int left=1,right=n,middle=0,ans=0;
	while(left<=right)
	{
		middle=(right+left)/2;
		if(check(middle))
		{
			right=middle-1;
			ans=middle;
		}
		else
		{ 
			left=middle+1; 
		} 
	} 
	cout<<(ans-1)*2<<endl;
	return 0;
}