Я пытаюсь выбрать не более 10 элементов из этого списка, чтобы получить более высокую возможную прибыль.Почти решен 0/1 Двумерный рюкзак в python
Item name | Item "Weight" | Item "Profit"
[A, 1084, 424],
[B, 1143, 391],
[C, 1205, 351],
[D, 1088, 328],
[E, 5, 21],
[F, 996, 241],
[G, 13, 23],
[H, 2, 9],
[I, 5, 13],
[J, 14, 21],
[K, 11, 18],
[L, 4, 12],
[M, 121, 59],
...
Total length: 249
Я обнаружил, что моя проблема может быть определена как 0/1 Bidimensional Knapsack problem. Вес будет первым измерением, а предел в 10 пунктов будет вторым измерением. Поэтому я пытался использовать различные решения с помощью python для оптимизации выбора.
После поиска различных источников, я не был в состоянии найден питон решение моей конкретной задачи:
- предел, определенный вес (где-то между 100-10.000)
- Каждый элемент может быть выбран только один раз
- Можно выбрать только 10 предметов
- Максимизируйте «прибыль»!
Наконец я нашел this Java решение, которое я пытался перевести, но сделал ошибку где-то функция работает почти правильно, но не может найти правильное решение. Я потратил пару дней, пытаясь найти, где код выходит из строя, но он несколько запутан.
from collections import namedtuple
Bounty = namedtuple('Bounty', 'name value size volume')
sack = Bounty('sack', value=0, size=800, volume=10)
items = results #A big list as mentioned above
dynNoRep = [[[0 for k in xrange(sack.volume+1)] for j in xrange(sack.size+1)] for i in xrange(
len(items) + 1)]
for i,item in enumerate(items):
for j in range(sack.size):
for h in range(sack.volume):
if item.size > j:
#pdb.set_trace()
dynNoRep[i][j][h] = dynNoRep[i-1][j][h]
elif item.volume > h:
dynNoRep[i][j][h] = dynNoRep[i-1][j][h]
else:
dynNoRep[i][j][h] = max(
dynNoRep[i-1][j][h], dynNoRep[i-1][j - items[i-1].size][h - items[i-1].volume] + items[i-1].value)
for i,item in enumerate(items):
for j in range(sack.size):
dynNoRep[i][j][sack.volume] = dynNoRep[i][j][sack.volume-1]
j = sack.size
h = sack.volume
finalSize = 0
finalValue = 0
finalVolume = 0
for i in range(len(items)-1, -1, -1):
#pdb.set_trace()
if dynNoRep[i][j][h] != dynNoRep[i-1][j][h]:
print"Value {} | Size {} | Volume {}".format(str(items[i-1].value), str(items[i-1].size), str(items[i-1].volume))
finalSize += items[i-1].size
finalValue += items[i-1].value
finalVolume += items[i-1].volume
j -= items[i - 1].size
h -= items[i - 1].volume
print('Final size {}/{}'.format(str(finalSize), str(sack.size)))
print('Final volume {}/{}'.format(str(finalVolume), str(sack.volume)))
print('Final value {}'.format(str(finalValue)))
И это выход, иногда показывают что-то лучше, но никогда не правильное решение:
Final size 0/800
Final volume 0/10
Final value 0
Контекст: Windows 8.1 32 бита. Ноутбук Ipython. Python 2.
Любые предложения по созданию кода? Заранее спасибо!