扫地机器人(第十届蓝桥杯研究生组)

题目:

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

QQ截图20210112140031.png

走廊内部署了 K 台扫地机器人,其中第 ii 台在第 Ai 个方格区域中。

已知扫地机器人每分钟可以移动到左右相邻的方格中,并将该区域清扫干净。

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

  1. 它们最终都返回出发方格,
  2. 每个方格区域都至少被清扫一遍,
  3. 从机器人开始行动到最后一台机器人归位花费的时间最少。

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

输出最少花费的时间。

在上图所示的例子中,最少花费时间是 66。

第一台路线: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≤1e5,
1≤Ai≤N

输入样例:

10 3
5
2
10

输出样例:

6

分析思路

最关键就是将题目条件转化,机器人工作时间T只与走过的区间长度L有关(T=2^(L-1)),因此题目转化为:求出一个最短区间,满足如下限制:

  • 区间的并集∪必须包含[1,n]所有的方格,即必须要能清扫所有方格
  • 每个区间内必须至少包含一个机器人,机器人在某个区间的任意位置工作时间都是一样的,无需限定机器人一定要在区间的中点

方法一:二分查找区间

可以从分析思路中得知区间1<=L<=n,因此用二分找到此区间长度L

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

/**
 * 
 */
public class Main {
    //下标均从1开始
    static int N=100000+5;
	static int[] robotIdx=new int[N];
	static int n;
	static int k;
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String[] line = reader.readLine().split(" ");
        n=Integer.parseInt(line[0]);
        k=Integer.parseInt(line[1]);
        for (int i = 0; i < k; i++) {
            line=reader.readLine().split(" ");
            robotIdx[i+1]=Integer.parseInt(line[0]);
        }
        //左闭右开,对机器人坐标排序,因为后面需要遍历机器人
        Arrays.sort(robotIdx,1,k+1);
        //找到能全覆盖的最小区间
        int l=1,r=n;
        while (l<r) {
            int mid=(l+r)>>1;
            if (check(mid)) {
                r=mid;
            }else{
                l=mid+1;
            }
        }
        System.out.println(2*(l-1));
    }
    //此区间长度能扫完则返回true,否则返回false
    private static boolean check(int length) {
        int hasClear=0;
        for (int i = 1; i <= k ; i++) {
            //这个扫地机器人必须能接上上一个扫过的位置
            if (robotIdx[i]-length<=hasClear) {
                if (robotIdx[i]<=hasClear) {
                    hasClear=robotIdx[i]+length-1;
                }else{
                    hasClear+=length;
                }
            }else{
                //接不上
                return false;
            }
        }
        return hasClear>=n;
    }
}

方法二:dfs查找区间

当区间长度为6时可能出现如下情况:

因此区间分布由两个变量决定,区间长度和第一个区间的显现的长度,从这两个出发dfs所有情况,时间复杂度约为:区间长度种类×第一个区间长度变化≈N²=1e10,可能会爆。

代码待补充。

posted @ 2022-03-23 10:11  思wu邪  阅读(171)  评论(0编辑  收藏  举报