你如何证明这个算法是最优的?

时间:2013-10-08 18:45:26

标签: algorithm optimization

我有这个问题:“如果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."

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

2 个答案:

答案 0 :(得分:0)

我认为这很接近,但我没有看到你考虑到可能出现故障的重量,看起来你有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:在价值指数的末尾。

取决于有多少值...实际上可以更快地向后搜索值索引并针对下一个最高值进行测试,这样您就不必为更大的项迭代尽可能多的值。 (例如,10KG将测试1KG,看看它不起作用.9KG将测试1KG并看到它有效,但也测试2KG并看到它不起作用,所以它需要1KG作为最佳值,这仍然只是2次迭代,而不是从8,5,2,1)开始的4次。

我希望这是有道理的。

答案 1 :(得分:0)

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

如果您有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,如果可能的话,或单独放入。在继续之前处理所有8个。
  • 如果您有7,请将其放入装有3的袋子中,如果没有,则装入2和1,如果不是,则装入单个2,如果不是,则装入1个以上的1个。在继续之前处理所有7个。
  • 如果你有一个6,那么把它放在4.如果没有,在这里它会变得棘手 ......
  • 此时你剩下的都是6s,5s,3s,2s,1s。现在,1s并不重要。您可以消除它们,找到最佳解决方案,然后重新添加它们。此外,如果你有至少两个5,将它们加在一起制作一个包(也很容易证明)。因此,你有6s,3s,2s,最多只有5个。如果你有5,那么如果可能的话,必须使用3,然后使用2或者你剩下的1。如果你没有3,那么你的5必须和你剩下的2s一样,然后是1s。
  • 所以现在我们剩下6s,3s和2s。现在它就像一个简单的游戏。你只有2s和3s,这才是最重要的。每个“6”允许你取一个“3”或两个“2”。在你用完6s后,你可以拿5个2s,或3个和3个2s,或者2个3s和2个2s,或者3个3s。现在,您可以使用动态编程来找到最佳解决方案。例如,让d[i, j, k]i 2s,j 3s和k 6s的最小行李数。可能有更好的解决方案。