Throwing the fattest people off of an overloaded airplane.

后端 未结 12 1705
迷失自我
迷失自我 2020-12-04 04:42

Let\'s say you\'ve got an airplane, and it is low on fuel. Unless the plane drops 3000 pounds of passenger weight, it will not be able to reach the next airport. To save t

相关标签:
12条回答
  • 2020-12-04 05:12

    @James has the answer in the comments: a std::priority_queue if you can use any container, or a combination of std::make_heap and std::pop_heap (and std::push_heap) if you want to use something like a std::vector.

    0 讨论(0)
  • 2020-12-04 05:16

    @Blastfurnace was on the right track. You use quickselect where the pivots are weight thresholds. Each partition splits one set of people into sets, and returns the total weight for each set of people. You continue breaking the appropriate bucket until your buckets corresponding to the highest weight people are over 3000 pounds, and your lowest bucket that is in that set has 1 person (that is, it can't be split any further.)

    This algorithm is linear time amortized, but quadratic worst case. I think it is the only linear time algorithm.


    Here's a Python solution that illustrates this algorithm:

    #!/usr/bin/env python
    import math
    import numpy as np
    import random
    
    OVERWEIGHT = 3000.0
    in_trouble = [math.floor(x * 10) / 10
                  for x in np.random.standard_gamma(16.0, 100) * 8.0]
    dead = []
    spared = []
    
    dead_weight = 0.0
    
    while in_trouble:
        m = np.median(list(set(random.sample(in_trouble, min(len(in_trouble), 5)))))
        print("Partitioning with pivot:", m)
        lighter_partition = []
        heavier_partition = []
        heavier_partition_weight = 0.0
        in_trouble_is_indivisible = True
        for p in in_trouble:
            if p < m:
                lighter_partition.append(p)
            else:
                heavier_partition.append(p)
                heavier_partition_weight += p
            if p != m:
                in_trouble_is_indivisible = False
        if heavier_partition_weight + dead_weight >= OVERWEIGHT and not in_trouble_is_indivisible:
            spared += lighter_partition
            in_trouble = heavier_partition
        else:
            dead += heavier_partition
            dead_weight += heavier_partition_weight
            in_trouble = lighter_partition
    
    print("weight of dead people: {}; spared people: {}".format(
        dead_weight, sum(spared)))
    print("Dead: ", dead)
    print("Spared: ", spared)
    

    Output:

    Partitioning with pivot: 121.2
    Partitioning with pivot: 158.9
    Partitioning with pivot: 168.8
    Partitioning with pivot: 161.5
    Partitioning with pivot: 159.7
    Partitioning with pivot: 158.9
    weight of dead people: 3051.7; spared people: 9551.7
    Dead:  [179.1, 182.5, 179.2, 171.6, 169.9, 179.9, 168.8, 172.2, 169.9, 179.6, 164.4, 164.8, 161.5, 163.1, 165.7, 160.9, 159.7, 158.9]
    Spared:  [82.2, 91.9, 94.7, 116.5, 108.2, 78.9, 83.1, 114.6, 87.7, 103.0, 106.0, 102.3, 104.9, 117.0, 96.7, 109.2, 98.0, 108.4, 99.0, 96.8, 90.7, 79.4, 101.7, 119.3, 87.2, 114.7, 90.0, 84.7, 83.5, 84.7, 111.0, 118.1, 112.1, 92.5, 100.9, 114.1, 114.7, 114.1, 113.7, 99.4, 79.3, 100.1, 82.6, 108.9, 103.5, 89.5, 121.8, 156.1, 121.4, 130.3, 157.4, 138.9, 143.0, 145.1, 125.1, 138.5, 143.8, 146.8, 140.1, 136.9, 123.1, 140.2, 153.6, 138.6, 146.5, 143.6, 130.8, 155.7, 128.9, 143.8, 124.0, 134.0, 145.0, 136.0, 121.2, 133.4, 144.0, 126.3, 127.0, 148.3, 144.9, 128.1]
    
    0 讨论(0)
  • 2020-12-04 05:19

    I would probably use std::nth_element to partition off the 20 heaviest people in linear time. Then use a more complex method to find and bump off the heaviest of the heavies.

    0 讨论(0)
  • 2020-12-04 05:21

    Assuming that, like people's weights, you have a good idea of what the maximum and minimum values are likely to be use a radix sort to sort them in O(n). Then simply work from the heaviest end of the list towards the lightest. Total running time: O(n). Unfortunately, there isn't an implementation of a radix sort in the STL, but it's pretty straightforward to write.

    0 讨论(0)
  • 2020-12-04 05:22

    You could make one pass over the list to get the mean and the standard deviation, then use that to approximate the number of people that have to go. Use partial_sort to generate the list based on that number. If the guess was low, use partial_sort again on the remainder with a new guess.

    0 讨论(0)
  • 2020-12-04 05:24

    This won't help for your proxy problem, however:

    For 1,000,000 passengers to drop 3000 pounds of weight, each passenger must lose (3000/1000000) = 0.003 lbs per person. That could be achieved through jettisoning every ones shirt, or shoes, or probably even fingernail clippings, saving everyone. This assumes efficient collection and jettison before the weight loss needed increased as the plane used more fuel.

    Actually, they don't allow fingernail clippers on board anymore, so that's out.

    0 讨论(0)
提交回复
热议问题