Google Kick Start:错误的Metal Harvest解决方案

时间:2020-10-06 05:39:31

标签: python algorithm optimization

我正在尝试练习Google Kick Start,并解决Metal Harvest Task

您负责部署机器人以从附近的小行星上收获Kickium。机器人的设计目的不是为了团队协作,因此在任何时间点只能收获一个机器人。在返回校准之前,单个机器人可以连续部署多达K个时间单位,无论在这段时间内花费多少时间进行收获。收获只能在特定的时间间隔内进行。这些时间间隔不重叠。在给定K和允许收获的时间间隔的情况下,在所有可能的时间收获最少需要部署多少个机器人?

我阅读了分析并得到了结果,但是我不明白为什么我的解决方案不起作用。提交时,我总是会收到“ WA”-错误的答案。

主要思想是,我首先对时间间隔进行排序,然后将其分为多个块,其中一个块中的所有间隔之间的时间步长少于K然后,在一个块中,我每K步连续部署机器人,即每个块需要math.ceil(chunk_len / K)个机器人。我不需要大块之间的机器人。

从概念上讲,对吧?它也通过了我的测试用例。 所以我猜,关于列表索引或边缘情况我有一些错误,但我不知道是什么。

import math


class Interval:
    def __init__(self, start, end):
        self.start = start
        self.end = end


class Solution:
    def __init__(self, max_time, intervals):
        self.max_time = max_time
        self.intervals = intervals

    def harvest_v1(self):
        """start harvesting and return min number of robots"""
        num_robots = 0

        # sort intervals with increasing start time --> O(N log(N))
        sorted_intervals = sorted(self.intervals, key=lambda interval: interval.start)

        # walk through intervals, starting at  --> O(N)
        chunk_start = sorted_intervals[0].start
        for i in range(1, len(sorted_intervals)):
            # calc duration to next interval and stop chunk if there's K or more time until the next interval
            time_to_next = sorted_intervals[i].start - sorted_intervals[i-1].end
            if time_to_next >= self.max_time:
                # then stop chunk and compute num robots needed for chunk
                chunk_len = sorted_intervals[i-1].end - chunk_start
                num_robots += math.ceil(chunk_len / self.max_time)
                # start a new chunk
                chunk_start = sorted_intervals[i].start

        # then still include last interval
        chunk_len = sorted_intervals[-1].end - chunk_start
        num_robots += math.ceil(chunk_len / self.max_time)

        return num_robots


# read input and generate output
num_tests = int(input())
for test in range(1, num_tests + 1):
    num_intervals, max_time = [int(k) for k in input().split()]
    intervals = []
    for interval in range(num_intervals):
        start, end = [int(k) for k in input().split()]
        intervals.append(Interval(start, end))

    sol = Solution(max_time, intervals)
    print("Case #{}: {}".format(test, sol.harvest_v1()))

任何提示将不胜感激!

1 个答案:

答案 0 :(得分:1)

您的方法可能适用于大多数测试用例,但有些极端情况可能会证明它是错误的。 试试这个测试用例,您将理解为什么失败:

    max_time = 6
    intervals = [Interval(1,3), Interval(4,7), Interval(11,16), Interval(17,22)]

正确的输出:3

您的程序输出:4

说明

您的代码标记chunk start = start of the first interval并向前循环,直到找到与前一个间隔>= max_time有时间间隔的间隔为止。它使用循环中当前间隔的robot deploymentschunk start计算到该间隔所需的end time。由于您的代码仅处理time_to_next >= self.max_time条件,因此相反的条件将成为问题。

在我前面提到的测试用例中,您的代码会将所有间隔放入单个块中,因为所有间隔之间的时间间隔小于max_time,但是最佳解决方案是将其间隔为2或3块。


如果您想尝试其他方法,请查看以下代码:

def harvest_v1(self):
    sorted_intervals = sorted(self.intervals, key=lambda interval: interval.start)
    robots_deployed = 0         # Keeps track of total robots deployed
    next_calibration_time = 0   # Keeps track of time for next robot calibration

    for interval in sorted_intervals:
        start_i = interval.start
        end_i = interval.end
        interval_duration = end_i - start_i

        if next_calibration_time <= start_i:    # If no robot has been deployed yet 
                                                # or previous robot has been sent for calibration, then
            
            # calculate the number of deployments required for current interval
            deployments_required = math.ceil(interval_duration / self.max_time)
            robots_deployed += deployments_required

            # calculate and track the time at which lastly deployed robot will be sent for calibration
            next_calibration_time = start_i + (deployments_required * self.max_time)

        elif next_calibration_time < end_i:     # If some robot is still working then

            # calculate the time remaining in current interval after currently working robot becomes unavailable
            remaining_duration = end_i - next_calibration_time

            # calculate the number of deployments required
            deployments_required = math.ceil(remaining_duration / self.max_time)
            robots_deployed += deployments_required

            # calculate and track the time at which lastly deployed robot will be sent for calibration
            next_calibration_time = next_calibration_time + (deployments_required * self.max_time)

    return robots_deployed