Объединить n монет с минимальными затратами, чтобы создать одну единственную монету

Из http://www.geeksforgeeks.org/amazon-interview-set-89/

У нас есть n золотых монет. Нам нужно объединить все n монет для создания одной единственной монеты, мы можем объединить две монеты сразу. Стоимость слияния две монеты равны стоимости этих монет. Как мы гарантируем, что стоимость слияния n монет в минимальном размере.

Ex: 5 ,8 , 4, 3, 9, 6
We will merge 3 and 4, cost=7 {Remaining coins: 5,8,9, 6,7}
Then we merge 5 and 6, cost=11 { Remaining coins: 11,8,9,7}
Then we merge 7 and 8, cost=15 { Remaining coins: 11,15,9}
Then we merge 9 and 11, cost=20 { Remaining coins: 20,15}
Then we merge 20 and 15, cost=35 { Remaining coins: 35}
Total cost: 7+11+15+20+35 = 88

Если бы мы объединили массив монет {5, 8, 4, 3, 9, 6} в разных мода:

Merging 5 and 8, cost=13 {Remaining coins: 13, 4, 3, 9, 6}
Merging 13 and 4, cost=17 {Remaining coins: 17, 3, 9, 6}
Merging 17 and 3, cost=20 {Remaining coins: 20, 9, 6}
Merging 20 and 9, cost=29 {Remaining coins: 29, 6}
Merging 29 and 6, cost=35 {Remaining coins: 35}
Total cost: 114

Как мы видим, стоимость в первом случае меньше. как получить минимальная стоимость слияния всех n монет;

это всего лишь пример, количество монет может быть в диапазоне 10 ^ 9

Ответ 1

Я не очень много думал об этом, но с головы до головы, похоже, что будет жадный подход: сортировать монеты и сначала сначала объединять самые маленькие. Интуиция заключается в том, что вы хотите "объединить" самую дорогую монету как можно реже.

Если у вас есть одна монета, все готово. Если у вас две монеты, у вас есть только один выбор. Рассмотрим случай с тремя монетами: A < B < C. Мы можем объединить их тремя способами:

A + B, (A + B) + C => 2A + 2B + C
A + C, (A + C) + B => 2A + 2C + B
B + C, (B + C) + A => 2B + 2C + A

Мы видим, что лучший вариант - слияние самых маленьких монет. См. Ответ "Билл" для получения ценной информации о том, как все это сделать, - комментарий, который я внес, копируется здесь:

Вы можете думать о значениях монет как о токенах, используемых в кодировке Хаффмана. Для очень частых токенов вам нужен короткий код. Я думаю, что Билл указывает, что "слияние" можно рассматривать как своеобразное движение вверх по дереву Хаффмана: количество раз, когда монета объединяется, - это расстояние от корня. Поэтому доказательство правильности алгоритма Хаффмана должно относиться к (также) жадному алгоритму, который я описываю, который в основном является Хаффманом, хотя и не для кодирования.

Ответ 2

Пусть C_s - оптимальная стоимость слияния S = [s_1, s_2, ..., s_n].

Тогда, если P и Q различны только в одном элементе (т.е. p_i = q_i, кроме точно одного i), при индексе j и p_j < q_j. Тогда имеем C_P <= C_Q.

В принципе, P и Q отличаются только одной монетой с P, имеющей меньшую. Тогда оптимальное слияние для P будет иметь меньшую стоимость, чем оптимальное слияние для Q.

Это доказывает, что жадный алгоритм @Patrick87 верен.

btw, это в основном кодировка Унарного Хаффмана!