Рассмотрим следующую задачу. В обороте находятся банкноты k различных номиналов: a1, a2, ..., ak рублей. Банкомат должен выдать сумму в N рублей при минимального количества банкнот или сообщить, что запрашиваемую сумму выдать нельзя. Будем считать, что запасы банкнот каждого номинала неограничены.
Рассмотрим такой алгоритм: будем выдавать банкноты наибольшего номинала, пока это возможно, затем переходим к следующему номиналу. Например, если имеются банкноты в 10, 50, 100, 500, 1000 рублей, то при N = 740 рублей такой алгоритм выдаст банкноты в 500, 100, 100, 10, 10, 10, 10 рублей. Подобные алгоритмы называют «жадными», поскольку каждый раз при принятии решения выбирается тот вариант, который кажется наилучшим в данной ситуации (чтобы использовать наименьшее число банкнот каждый раз выбирается наибольшая из возможных банкнот).
Но для решения данной задачи в общем случае жадный алгоритм оказывается неприменимым. Например, если есть банкноты номиналом в 10, 60 и 100 рублей, то при N = 120 жадный алгоритм выдаст три банкноты: 100 + 10 + 10, хотя есть использующий две банкноты: 60 + 60. А если номиналов банкнот только два: 60 и 100 рублей, то жадный алгоритм вообще не сможет найти решения.
Но эту задачу можно решить при метода динамического программирования. Пусть F(n) -- минимальное количество банкнот, которым можно заплатить сумму в n рублей. Очевидно, что F(0) = 0, F(a1) = F(a2) =...= F(ak) = 1. Если некоторую сумму n невозможно выдать, будем считать, что F(n) = $ \infty$ (бесконечность).
Выведем рекуррентную формулу для F(n), считая, что значения F(0), F(1), ..., F(n - 1) уже вычислены. Как можно выдать сумму n? Мы можем выдать сумму n - a1, а потом добавить одну банкноту номиналом a1. Тогда нам понадобится F(n - a1) + 1 банкнота. Можем выдать сумму n - a2 и добавить одну банкноту номиналом a2, для такого понадобится F(n - a2) + 1 банкнота и т. д. Из всевозможных выберем наилучший, то есть:
F(n) = min(F(n - a1), F(n - a2),..., F(n - ak)) + 1.
Теперь заведем массив F[n+1], который будем последовательно заполнять значениями выписанного рекуррентного соотношения. Будем предполагать, что количество номиналов банкнот хранится в переменной int k, а сами номиналы хранятся в массиве int a[k].
const int INF=1000000000; // Значение константы }бесконечность}
int F[n+1];
F[0]=0;
int m, i;
for(m=1; m<=n; ++m) // заполняем массив F
{ // m - сумма, которую нужно выдать
F[m]=INF; // помечаем, что сумму m выдать нельзя
for(i=0; i<k; ++i) // перебираем все номиналы банкнот
{
if(m>=a[i] && F[m-a[i]]+1<F[m])
F[m] = F[m-a[i]]+1; // изменяем значение F[m], если нашли
} // лучший выдать сумму m
}
После окончания этого алгоритма в элементе F[n] будет храниться минимальное количество банкнот, необходимых, чтобы выдать сумму n. Как теперь вывести представление суммы n при банкнот? Опять рассмотрим все номиналы банкнот и значения n - a1, n - a2, ..., n - ak. Если для какого-то i окажется, что F(n - ai) = F(n) - 1, значит, мы можем выдать банкноту в ai рублей и после этого свести задачу к выдаче суммы n - ai, и так будем продолжать этот процесс, пока величина выдаваемой суммы не станет равна 0:
if (F[n]==INF)
cout<<"Требуемую сумму выдать невозможно"<<endl;
else
while(n>0)
for(i=0;i<k;++i)
if (F[n-a[i]]==F[n]-1)
{
cout<<a[i]<<" ";
n-=a[i];
break;
}
не удаляйте это
Задание 1: 4132
4 Экзамен | ЕГЭ | Информатика | Литература
1 Экзамен | ЕГЭ | Информатика
3 Экзамен | ЕГЭ
2 Экзамен & ЕГЭ & Информатика
Задание 2: 3124
3 рыбки
1 рыбки & аквариум
2 рыбки & аквариум & гуппи
4 рыбки & аквариум & гуппи & купить
Задание 3: 3421
3 Сок | Нектар
4 Сок
2 Сок & Апельсин
1 Сок & Апельсин & Яблоко
Задание 4: 2134
2 волейбол | баскетбол | подача | блок
1 волейбол | баскетбол | подача
3 волейбол | баскетбол
4 волейбол & баскетбол & подача
Задание 5: 2341
2 алгоритм & сжатие & графика & архиватор
3 алгоритм & сжатие
4 алгоритм | (сжатие & графика)
1 сжатие | графика | алгоритм
Задание 6: 1423
1 (Автомобили – Ford) & новые
4 Автомобили – Ford
2 Автомобили
3 Автомобили | Ford
Задание 7: 3124
3 отдых & Сочи & Адлер
1 отдых & (Сочи | Адлер)
2 отдых & (море | Сочи | Адлер)
4 отдых | Сочи | Адлер
Задание 8: 4123
4 строительный & стоимость & купить & купить
1 строительный & стоимость & купить
2 строительный | материал | купить
3 строительный | материал | стоимость | купить
Задание 9: 5000
Новосибирск 3300
Красноярск 2200
Новосибирск & Красноярск 500
Новосибирск | Красноярск 5000
Задание 10:
Атос & Портос 335
Атос & Арамис 225
Атос & Портос & Арамис 120
Атос & (Портос | Арамис) 440
Графические подтверждения:
В монозаписи 1 дорожка, в стереозаписи 2.
Из формулы выводим формулу для времени
время = объем / (частота дискретизации * разрядность кода * кол-во дорожек)
переводим объем в байты
3,5 Мбайт = 3584 кбайт = 3670016 байт
переводим разрядность в байты
16 бит = 2 байта
Считаем время
t = 3670016 / (44100 * 2 * 2) = 3670016 / 176400 = 20,8 сек