扫地机器人

扫地机器人

题目描述

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

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

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

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

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

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

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

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

输出描述

输出一个整数表示答案。

输入样例

10 3
5
2
10

输出样例

6

解题思路

本题为一道比较明显的二分题目。

题目要求最少花费时间。由于每个机器人的工作时间可能不同,那么这些机器人各自的花费时间中的最大值(设为 t )的就是本题要求的答案, 需要做的是使得 t 最小。将最大花费时间(t)最小化,显然需要使用二分求解。 假设某个机器人需要清扫 a,b,c,d 四个格子,因为这个机器人清扫完还需要回到最初始的位置,所以无论这个机器人初始位置在什么地方, 其清扫路径的本质都是重复两次 a 到 b,b 到 c,c 到 d 的过程,花费时间为 6,由此,假设某个机器人清扫的格子范围为 len, 那么这个机器人花费的时间为 (len-1)*2。所以只需要对机器人清扫的范围(len)进行二分即可,最后的答案为 t=(len-1)*2。 显然当每个机器人清扫的范围大小相同时,花费时间最小。 可以对清扫范围进行二分,然后验证其答案的正确性即可,判断条件是清扫范围可以使得每个格子都能够扫到 可以明显的知道,最左边的格子由左边第一台机器人清扫,花费时间是最少的,在此可以采用贪心的思想, 让每台机器人都要优先清扫其左边还未扫的到格子,然后再往右扫,在二分得到的范围下往右扫得越多越好, 这样可以减少右边下一个机器人需要往左扫的范围,增加其往右扫的范围,以此类推,可减少清扫时间。

综上,本题采用二分加贪心的思想解答。

代码

#include<bits/stdc++.h>
using namespace std;

int robot[1000005];   //机器人位置
int n,k;

int check(int len){
	
	int step=0;   //step代表清扫到了哪个位置
	for(int i=0;i<k;i++){ 
		if(robot[i]-len<=step){   //如果当前机器人只扫左侧,能够覆盖左侧未清扫的位置,则可进行当前机器人的清扫
			if(robot[i]<=step)    //如果当前机器人已经处于清扫过的位置,则当前机器人只扫右侧区域
				step=robot[i]+len-1;
			else             //否则从上一个清扫到的位置继续
				step+=len;
		}
		else   //当前机器人只扫左侧,不能覆盖左侧未清扫的位置,当前方案不可行,返回
			return 0;
	}
	if(step>=n)   //表示当前方案可行
		return 1;
	else          //表示当前方案不可行
		return 0;	
}



int main(){
	
	int cnt;
	scanf("%d %d",&n,&k);
	
	for(int i=0;i<k;i++)
		scanf("%d",&robot[i]);
	
	sort(robot,robot+k);   //首先对机器人的位置进行排序
	int l=0,r=n;
	while(l<=r){
		
		int mid=(l+r)/2;
		if(check(mid)){    //如果当前方案可行,则缩小清扫范围,试图寻找更小的方案
			r=mid-1;
			cnt=mid;
		}
		else              //如果方案不可行,则扩大清扫范围,寻找可行方案
			l=mid+1;  
		
	}
	
	printf("%d",(cnt-1)*2);
	return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值