Процесс создания мультипликационного фильма состоит из многих этапов. Сначала придумывается сюжет мультика, пишется его сценарий, где описывают поэтапно все события, которые в нем будут происходить, создаются эскизы героев. Но не всем известно, что для того чтобы такой нарисованный персонаж ожил и находился в движении в течение одной минуты, понадобится более чем полторы тысячи рисунков. Такие изображения называются кадрами. Они столь быстро меняются один за другим, что человеческие глаза воспринимают это чередование, как живую картинку. Чтобы форма объектов изменялась плавно, за одну секунду должно поменяться 12 – 16 кадров. Такой принцип имитации движения ещё называют анимацией.
Рассмотрим следующую задачу. В обороте находятся банкноты 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:
Процесс создания мультипликационного фильма состоит из многих этапов. Сначала придумывается сюжет мультика, пишется его сценарий, где описывают поэтапно все события, которые в нем будут происходить, создаются эскизы героев. Но не всем известно, что для того чтобы такой нарисованный персонаж ожил и находился в движении в течение одной минуты, понадобится более чем полторы тысячи рисунков. Такие изображения называются кадрами. Они столь быстро меняются один за другим, что человеческие глаза воспринимают это чередование, как живую картинку. Чтобы форма объектов изменялась плавно, за одну секунду должно поменяться 12 – 16 кадров. Такой принцип имитации движения ещё называют анимацией.
Объяснение:
Думаю так
Рассмотрим следующую задачу. В обороте находятся банкноты 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;
}
не удаляйте это