6.9.1 Задача
Рассмотpим следующую задачу.
4
Для срочной покупки квартиры мистер Смит получил в банке заем, эквивалент-
ный Q долларам. Он должен выплатить свой долг в течении K лет, выплачивая
каждый год еще и проценты P . Это значит, что к концу каждого года долг мистера
Смита вырастает на P ∗Q
1
/100 ( Q
1
– долг на начало года ) и его текущие выплаты
вычитаются из общей суммы с учетом процентов.
В первый год мистер Смит хочет заплатить такую минимальную сумму, которая
позволит ему выплатить весь долг точно за K лет. В каждый последующий год он
хочет выплачивать или точно такую же сумму, как в предшествующий год, либо на
один цент меньше. Кроме того, он хочет закончить выплачивать долг без переплаты
даже одного цента к концу K-го года.
Банк выполняет начисление процентов с точностью в один цент и производит
начисление процентов в конце каждого года. При вычислении процентов результат
немедленно округляется до ближайшего цента, причем 0.5 центов округлается до 1
цента.
Ограничения на данные. 10 ≤ Q ≤ 1000000, 0 ≤ P ≤ 100, 1 ≤ K ≤ 100.
Входные данные. Входной файл содержит три числа Q, P и K.
Результаты. Выходной файл содержит выплаты. Если решение невозможно, вы-
ходной файл должен содержать единственную строку с текстом "Impossible". В про-
тивном случае требуется вывести выплачиваемую сумму и число лет, в течение ко-
торых эта сумма выплачивается, в виде строки: "$X for Y year(s)"
Решение.
Рассмотрим рекурсивную схему решения задачи. Пусть функция Solve(Q, M, i)
решает задачу распределения выплат и выполняет следующие действия:
а) возвращает значение 1, если при условии выплаты в текущем году M центов
на последующих шагах задача успешно решается ( здесь i - число лет до окончания
срока всех выплат, Q - общая сумма к выплате );
б) возвращает 0, если решение невозможно.
Если известно, что за i-ый год выплатили M центов, то по условию задачи в новом
(i − 1)-ом году можно выплатить M или M − 1 центов. Таким образом, достаточно
вычислить новое значение общей суммы к выплате и проверить два варианта выплат
M и M − 1 центов. Сначала надо вычислить значение нового долга по формуле
percent = 1 + P/100;
NewQ = percent ∗ Q − M + 0.5001.
Сразу следует отметить, что эта формула является абсолютно неправильным с
точки зрения языка С++ оператором, т.к. в ней не учтено представление разных ти-
пов данных в памяти ЭВМ и операции приведения типов (смотрите текст программы,
где указаны соответствующий операторы ). После того, как начислили проценты и
заплатили в данном году, делаем попытку дальнейшего решения:
if (Solve(NewQ, M-1, year-1) || Solve(NewQ, M, year-1)) return 1;
Обратите особое внимание на порядок вызова функции
Solve(...M − 1...) и Solve(...M...)
4
1997-1998 ACM Northeastern EuropeanRegionalProgramming Contest
176