Рассмотрим следующую задачу. В обороте находятся банкноты 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+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:
Чтобы контрольная работа получила высший , необходимо как следует постараться: изучить теорию написания контрольных работ, посмотреть методички и гост, составить план и многое другое. как видите, решение контрольной работы не такая уж и простая . но продвинутые студенты, которые знают цену своему времени и силам, заказывают решение контрольных работ у нас. это быстро, качественно и доступно каждому. мы не пользуемся услугами посредников, чему цены на наши услуги значительно ниже, а работа выполняется быстрее. образец плана контрольной работы конечно, всегда будут студенты, которые любят самостоятельно писать контрольные работы. им мы тоже стараемся всеми силами. поэтому мы подобрали несколько качественных примеров плана контрольных работ, которые демонстрирует практически идеальное выполнение плана. опираясь на эти примеры, не забывайте и о теории. план контрольной работы должен быть детально проработан. в нем вы должны указать, сколько точно будет разделов, глав и параграфов. кроме того, им нужно дать названия, которые будут уникальными (т.е. не повторяются в тексте работы больше одного раза). план также определить, какой объем займет ваша контрольная работа. распределяя главы, продумывайте, что вы будете в них писать, какая информация вам для этого понадобится, что вам для этого не хватает. если вы будете четко следовать нашим советам, вы без труда сможете самостоятельно написать план к любой контрольной работе. взято со страницы:
Рассмотрим следующую задачу. В обороте находятся банкноты 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;
}
не удаляйте это