Задача взята с сайта e-olimp
Условие:
В некотором царстве жил Змей Горыныч. У него было [latex]N[/latex] голов и [latex]M[/latex] хвостов. Иван-царевич решил уничтожить губителя человеческих душ, для чего ему его кума Баба Яга подарила волшебный меч, так как только им можно убить Змея Горыныча. Если отрубить одну голову, то на её месте вырастает новая, если отрубить хвост, то вместо него вырастет 2 хвоста. Если отрубить два хвоста, то вырастает 1 голова, и только когда отрубить 2 головы, то не вырастет ничего. Змей Горыныч гибнет только в том случае, когда ему отрубить все головы и все хвосты. Определить минимальное количество ударов мечом, нужное для уничтожения Змея Горыныча.
Входные данные:
Два числа [latex]N[/latex], [latex]M[/latex] ([latex]0[/latex] [latex]<=[/latex][latex]N[/latex], [latex]M[/latex][latex]<=[/latex][latex]1000[/latex]).
Выходные данные:
Единственное число – минимальное количество ударов мечом, или -1, если уничтожить Змея Горыныча невозможно.
Тесты:
N | M | Количество ударов |
3 | 3 | 9 |
3 | 0 | -1 |
0 | 9 | 12 |
0 | 0 | 0 |
3 | 2 | 3 |
19 | 114 | 95 |
Решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <iostream> using namespace std; int main() { int N, M, count = 0; cin>>N>>M; if ((N%2!=0)&&(M==0)) //здесь проверяется, возможно ли убить Горыныча { cout<<"-1"<<endl;// вывод "-1" в противном случае } else { while ((N>0)||(M>0)) //цикл будет выполняться до тех пор, пока существует хоть одна голова или хвост { if (M%2==1) //если хвостов нечетное количество, то посредством отрубания одного хвоста увеличиваем число их на 1 { count++;// здесь и далее таким образом будет увеличиваться счетчик надрезов M++; } if ((N%2==1)&&(M>=2)) //если голов нечетное количество, то отрубая два хвоста увеличиваем количество голов на 1 { M-=2; N++; count++; } if ((M%2==0)&&(N%2==0)&&((N+(M/2))%2==0)) //если число голов и хвостов четное, и если количество хвостов при делении на два дает четное число { count=count+M/2+((N+M/2)/2);//то увеличиваем счетчик надрезов N=0; M=0;//и обнуляем количество голов и хвостов для выхода их цикла } else //если не выполняется какое-либо из условий прошлого ветвления, то увеличиваем количество хвостов на 1 { M++; count++; } } cout<<count<<endl;//выводим количество ударов } return 0; } |
Описание решения:
При решении данной задачи было рассмотрено несколько случаев.
- Змея Горыныча убить невозможно. Это возможно только в том случае, когда у него нечетное количество голов, и нет ни одного хвоста, так как при наличии хотя бы одного хвоста становится возможным увеличение количества хвостов и голов до необходимого, путем отрубания одного, или двух хвостов соответственно. Чтобы определить возможность уничтожения Змея, делаем проверку: если количество голов нечетное и хвостов нет, то выводим «-1». Если эти условия не выполняются, то переходим ко второму пункту решения.
- Змей Горыныч может быть убит. Это означает, что у Змея есть хотя бы один хвост, или четное количество голов. В таком случае, мы работаем внутри цикла, при каждом проходе которого проверяется, выполняются ли описанные выше условия:
13while ((N>0)||(M>0)) //цикл будет выполняться до тех пор, пока существует хоть одна голова или хвост
- Если количество хвостов [latex]M[/latex] нечетное, то отрубаем один хвост, на месте которого вырастает два новых, и увеличиваем счетчик ударов [latex]count[/latex] на один.
- Если количество голов нечетное, и хвостов больше одного, то отрубаем два хвоста, тем самым увеличивая количество голов на 1, и увеличиваем счетчик.
- Если количество голов и хвостов четное, и если количество хвостов при делении на два дает четное число, то мы увеличиваем счетчик на [latex]M/2+((N+M/2)/2)[/latex], и приравниваем количество голов и хвостов нулю.
- Если какое-то из условий пункта 3 не выполняется, то увеличиваем количество хвостов на 1, и увеличиваем счетчик ударов.
- Повторяем алгоритм до тех пор, пока не убьем Горыныча.
После выхода из цикла в счетчике [latex]count[/latex] находится минимальное число ударов, необходимое для уничтожения Змея Горыныча. Выводим его на экран, и переходим на новую строку с помощью команды [latex]endl[/latex].
Здесь код программы на сайте ideone.com.
Для перехода к странице на e-olimp с полностью выполненным данным заданием щелкните здесь.
Я засчитываю Ваше решение поскольку аккуратно проделана большая работа, но…
Анализ условия задачи показывает, что удар мечом может привести к следующим последствиям:
1) tails ++ (tails > 0)
2) tails -= 2; heads++ (tails > 1)
3) heads -= 2 (heads > 1)
Сразу вывод. Нужно чтобы heads + tails / 2 было чётным и tails тоже.
Алгоритм работы Ивана-царевича таков:
— Если хвостов нечётное число то делаем 1),
— Если heads + tails / 2 нечётное, то делаем 1) 1) ,
— Делаем 2) (tails/2)-раз,
— Делаем 3) (heads/2)-раз.
Поскольку делить на 2 мы умеем одной операцией, циклы нам не понадобятся:
Я понял, спасибо большое за объяснение