import copy


def parallel_worker_time(step_dict, num_workers, min_time):
    """
    A more complicated version of the above, which would be equivalent to calling the above with step_dict, 1, 0.
    This involves using multiple workers, a minimum overhead per step, and steps that take time corresponding to their
    letter (e.g. A = 1, B = 2, etc).

    We want to figure out the minimum amount of time needed to complete the construction.

    :param step_dict: the step data as generated by create_step_dict
    :param num_workers: the number of workers
    :param min_time: the overhead time for a given step
    :return: the total number of time units to complete construction

    >>> parallel_worker_time({'A': ['C'], 'F': ['C'], 'B': ['A'], 'D': ['A'], 'E': ['B', 'D', 'F']}, 2, 0)
    15
    """
    step_dictp = copy.deepcopy(step_dict)

    # Get the set of all steps.
    steps = set()
    for values in step_dictp.values():
        steps.update(values)
    for keys in step_dictp.keys():
        steps.update(keys)

    # The amount of time left per step.
    step_time_left = {k: min_time + ord(k) - ord('A') + 1 for k in steps}

    # Keep track of how many time units have passed.
    time_units = 0

    # Workers keep working on their task until done.
    worker_tasks = [None] * num_workers

    while len(step_time_left) > 0:
        # Symmetric difference between the keys and the steps are what can be done.
        candidates = sorted([s for s in steps if s not in step_dictp.keys() and s not in worker_tasks])

        # We can work on exactly num_workers of them.
        steps_done = []

        # Assign candidates to workers.
        t = 0
        for w in range(num_workers):
            if worker_tasks[w] is not None:
                continue
            if len(candidates) > t:
                worker_tasks[w] = candidates[t]
                t += 1

        # Now do the work.
        for cnum in range(num_workers):
            c = worker_tasks[cnum]
            if c is None:
                continue
            step_time_left[c] -= 1
            if step_time_left[c] == 0:
                del step_time_left[c]
                steps_done.append(c)
                steps.remove(c)
                worker_tasks[cnum] = None

        # The work has been done. Remove the done steps from their requirements.
        for s in steps_done:
            keys = list(step_dictp.keys())
            for k in keys:
                if s in step_dictp[k]:
                    step_dictp[k].remove(s)
                    if len(step_dictp[k]) == 0:
                        del step_dictp[k]

        time_units += 1

    return time_units