【问题标题】:How do you prove this algorithm is optimal?你如何证明这个算法是最优的?
【发布时间】:2013-10-09 03:18:41
【问题描述】:

我有这个问题:“给定 n 件重量从 1 公斤到 10 公斤不等的物品,你如何在最少数量的袋子之间分配它们,知道每个袋子不能容纳超过 10 公斤。”。

我尝试通过将物品从最重到最轻分类来解决这个问题,如果它们适合就将它们放入一个袋子中,如果它们不适合则创建一个新袋子。如果是这种情况,则从剩余物品的最重到最轻重新开始。这是我的代码:

list_of_items=raw_input("Input the items' weights (separated by spaces): ").split()

for i in range(len(list_of_items)):
        list_of_items[i]=int(list_of_items[i])

list_of_items.sort()
list_of_items.reverse()

while list_of_items[0]>=10:
        list_of_items=raw_input("You have input an item wheighing over 10kg: ").split()
        for i in range(len(list_of_items)):
                list_of_items[i]=int(list_of_items[i])

        list_of_items.sort()
        list_of_items.reverse()

set_of_bags=[] #In this list we'll store the bags

while(len(list_of_items)!=0):

        weight=0
        bag=[] #creates a new bag

        for item in list_of_items: #cycle copies items to bag
                if item+weight<=10:
                        bag.append(item)
                        weight+=item
        set_of_bags.append(bag) #adds bag to set_of_bags

        for item in bag: #deletes the items that have been put in set_of_bags from original list
                list_of_items.remove(item)

# output
n=0
for bag in set_of_bags:
        n+=1
        weight=0
        for j in bag:
                weight += j
        print "bag #"+str(n), bag, "=>", weight, "kg."

我相信这给出了正确的答案,但我不知道如何证明它。有什么帮助吗?

【问题讨论】:

标签: algorithm optimization


【解决方案1】:

当然,这不是最优的。一般来说,如果你有一个非平凡的算法对某物进行排序,然后使用“贪婪方法”,即选择最小或最大的东西,而你不确定为什么这是正确的,那么它可能是错误的。特别是如果您遇到整数优化问题。

如果您有 3, 3, 3, 3, 4, 4,那么您的算法最终将使用三个袋子而不是两个。

你的算法:

Bag 1: 4, 4
Bag 2: 3, 3, 3
Bag 3: 3

最佳:

Bag 1: 4, 3, 3
Bag 2: 4, 3, 3

现在,只是为了表明其他一些启发式方法也是错误的,看看这个例子:3, 3, 4, 6, 7, 7。如果你从最低到最高,将3, 3, 4 放在一个袋子里,你最终会得到四个袋子而不是三个袋子。同样的例子表明,仅仅因为你可以装满一个袋子并不意味着你应该这样做。 (但是,如果您只有两个组合在一起的物品,例如 73,那么您可以将它们放在一个袋子里,然后完全忘记它们。)

最后,看看3, 3, 3, 3, 4, 4, 4, 4。如果你从最低点开始,你会得到四袋:

Bag 1: 3 3 3
Bag 2: 3 4
Bag 3: 4 4
Bag 4: 4

如果你从最高处走,你会得到四个袋子:

Bag 1: 4 4
Bag 2: 4 4
Bag 3: 3 3 3
Bag 4: 3

但是,你可以得到三个包:

Bag 1: 4 3 3
Bag 2: 4 3 3
Bag 3: 4 4 

这是你可以做的(我省略了证明):

  • 如果您有 10 个,请将其放入单独的袋子中。首先处理所有 10 人。
  • 如果你有一个 9,如果可能的话,把它放在一个有 1 的袋子里,或者单独放在一个袋子里。在继续之前处理所有 9。
  • 如果您有一个 8,请将其放入一个袋子中,如果可能的话,有一个 2,或者有两个 1,如果可能,或者有一个 1,如果可能,或者单独放置。在继续之前处理所有 8。
  • 如果你有一个 7,把它和一个 3 一起放在一个袋子里.在继续之前处理所有 7。
  • 如果你有一个 6,就把 if 和一个 4 放在一起。如果没有,这里就很棘手了...
  • 此时您只剩下 6s、5s、3s、2s、1s。现在,1 并不重要。您可以消除它们,找到最佳解决方案,然后将它们添加回来。此外,如果您至少有两个 5,请将它们加在一起并制作一个袋子(也很容易证明)。因此,你有 6s、3s、2s,最多有一个 5。如果你有一个 5,那么如果可能的话,它必须与 3 一起使用,然后与 2 或你剩下的任何 1 一起使用。如果你没有 3,那么你的 5 必须和你剩下的 2 一样多,然后是 1。
  • 所以现在我们还剩下 6s、3s 和 2s。现在它就像一个简单的游戏。你只有 2s 和 3s,这很重要。每个“6”允许您取一个“3”或两个“2”。在你用完 6 之后,你可以拿 5 个 2,或者一个 3 和三个 2,或者两个 3 和两个 2,或者三个 3。现在您可以使用动态规划来找到最佳解决方案。例如,让d[i, j, k]i 2s、j 3s 和k 6s 的最小袋数。可能会有更好的解决方案。

【讨论】:

    【解决方案2】:

    我认为这很接近,但我认为您没有考虑可能出现故障的重量,看起来如果您有 9 公斤、5 公斤、1 公斤的物品。它会添加 9 公斤的物品,发现 5 公斤的东西太多了,然后跳到下一个袋子,即使 1 公斤的物品适合。

    我并不像大多数人那样了解 Python 优化,但我认为最快的会是。

    获取原始值,(10KG、5KG、8KG、2KG、2KG、1KG、10KG、9KG); 分类/索引重量(10KG:2、9KG:1、8KG:1、5KG:1、2KG:2、1KG:1)

    首先用最重的值开始填充袋子,如果重量超过尝试添加下一个最大的索引,直到袋子是 A: full 或 B: 在 value 索引的末尾。

    取决于有多少值...实际上可能会更快地向后搜索值索引并针对下一个最高值进行测试,这样您就不必为较大的项目迭代尽可能多的值。 (比如10KG测1KG看不行。9KG测1KG看行,也测2KG看不行,所以取1KG为最佳值,这还是只有2 次迭代,而不是从 8, 5, 2 ,1) 开始的 4 次迭代。

    我希望这是有道理的。

    【讨论】:

    • 先添加最大的可用权重后,如果再添​​加最小的可用值会怎样?
    • 好点!!由于该过程本质上是还原性的,因此实际上会使其更快!
    猜你喜欢
    • 2022-10-25
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多