e-olymp 15. Мышка и зернышки

Условие задачи:

В индийском храме пол прямоугольной формы выложен одинаковыми квадратными плитками 1 х 1, на каждую из которых высыпано от 0 до k зернышек (k ≤ 30000). Размеры пола m х n. Мышка выбегает из левого нижнего угла пола храма и двигается к входу в другую норку, расположенную в противоположном углу. Мышка может двигаться только вправо или вперед, собирая все зернышки с плитки, на которой она находится.

Найти маршрут, двигаясь по которому мышка соберет наибольшее количество зернышек.

Входные данные:

Первая строка содержит числа m и n – размеры пола (1 ≤ m, n ≤ 100). Далее идет m строк, начиная сверху, в каждой из которых размещено n чисел – количество зернышек на соответствующей плитке.

Выходные данные:

Вывести маршрут движения мышки в формате: RRFFFRF (F – шаг вперед, R – шаг вправо).

Тесты:

Входные данные Выходные данные
2 3
3 2 4
1 5 1
RFR
4 4
34 5 7 8
7 8 9 23
1 2 909 54
3 4 8 0
RRFRFF
7 8
23 4 7 8 94 23 5 6
2 9 7 56 83 5 44 2
1 2 3 4 5 6 7 8
8 7 6 5 4 32 2 1
90 87 3 5 4 3 2 5
28 75 60 94 33 3 2 7
76 92000 402 28 3 2 11 200
RFRRFFFFRFRRR

Код на С++:

Код на Java:

Описание решения задачи:

Представим пол индийского храма в виде двумерного массива. Т.к по условию движение мышки начинается с левого нижнего угла, при заполнении произойдет сдвиг, где позиция с изначальным номером [latex][n-1][0][/latex] примет позицию под номером [latex][0][0][/latex] и так далее пока данный сдвиг не достигнет плитки с номером [latex][n-1][0][/latex], где станет клеткой [latex][n-1][m-1][/latex]. Далее с помощью обхода в несколько циклов пересчитаем ячейки массива [latex]X[/latex] так, чтобы [latex]X[i][j][/latex] содержало максимальное количество зернышек, которое можно собрать по достижении плитки [latex](i, j)[/latex]. Переместимся в конец массива, в позицию под номером [latex]X[n-1][m-1][/latex]. Двигаясь в начальную клетку по закону, что предыдущая клетка слева или снизу должна содержать максимальное количество зернышек из всех возможных путей мыши, записываем в строку соответствующую букву, которая указывает на сделанный ход. По достижению цели мы получаем строку почти с готовым ответом. Перевернем ее, и теперь она указывает правильный путь не с конца в начало, а с начала в конец, что и требовалось. Выведем ответ.

Код задачи на с++
Код задачи на Java
Засчитанное решение на C++
Засчитанное решение на Java

Related Images:

Вычисление математических выражений

Условие задачи:
Пусть дана строка, которая является математическим выражением, содержащим числа, переменные и различные операции. Требуется вычислить его значение.

Помимо создания прототипа работы элементарного калькулятора, рассмотрим решение одной из подзадач — «Многочлен», найденную на просторах сайта e-olymp.

Входные данные:

В первой строке входного файла записано математическое выражение. Между операндами используются бинарные операторы ([latex]+[/latex], [latex]–[/latex], [latex]\ast[/latex], [latex]/[/latex], [latex]\wedge[/latex]) и унарный знак ([latex]–[/latex]). Если данное выражение представляет собой многочлен, то каждый одночлен записывается как [Коэффициент*]x[^Степень] или [Коэффициент], где [Коэффициент] — натуральное число, не превосходящее 100, x — символ переменной (всегда маленькая латинская буква [latex]x[/latex]), [Степень] — натуральное число, не превосходящее 4. Параметры, взятые в квадратные скобки, могут быть опущены. Во второй строке будет записано одно целое число — значение x. Все числа в исходном файле по модулю не превосходят 100. Количество одночленов не более 10 (могут быть одночлены одинаковой степени).

Выходные данные:

В выходной файл нужно записать одно число — результат вычисления данного математического выражения.

Тесты:

Входные данные Выходные данные
16-(4^3+52/2) -74
-2+x^1-3*x^2+x^2+100*x^3-2*x -7 -34393
-2*x^2+16*x^3-x (-3)^4 8489853
x^2-5*x+15-8*x^4 0 15

Код на с++:

Описание решения задачи:

В основе решения данной задачи лежит алгоритм, который переводит математические выражения в обратную польскую нотацию, что в дальнейшем позволяет решать данные выражения. Особенностью данной записи, в отличие от привычных нам, является постфиксная форма представления, где операторы математической формулы размещены после своих операндов.
Рассмотрим само решение. На входе программа получает две строки: одна из них представляет само математическое выражение/многочлен — [latex]formula[/latex] и при необходимости вторую — [latex]x[/latex], где передается значение переменной, использованной в многочлене. Если же на вход поступил не многочлен, данная строка сразу же идет на преобразование из инфиксной формы(оператор размещен между операндами) в постфиксную. В ином случае, с помощью встроенных библиотечных функций класса [latex]string[/latex] мы заменяем все переменные на вторую строку [latex]x[/latex] и выполняем точно такую же работу. Разберем ближе сам алгоритм преобразования строки и ее подсчета. Заведём два стека: [latex]value[/latex] — для чисел, [latex]op[/latex] — операций и скобок. Для второго стека является основным предусловие, что все операции упорядочены в нём по строгому убыванию приоритета, если двигаться от вершины стека. Будем идти слева направо по выражению в обратной польской нотации; если текущий элемент — число, то кладём на вершину стека [latex]value[/latex] его значение; если же текущий элемент — операция, то достаём из стека два верхних элемента (или один, если операция унарная), применяем к ним операцию, и результат кладём обратно в стек. Итого в [latex]value[/latex] останется один элемент — значение выражения.

Код задачи на с++
Засчитанное решение на e-olymp

Related Images:

e-olymp 1947. Конденсация графа

Условие задачи:

Для заданного ориентированного графа найти количество ребер в его конденсации.

Конденсацией орграфа G называют такой орграф G’, вершинами которого служат компоненты сильной связности G, а дуга в G’ присутствует только если существует хотя бы одно ребро между вершинами, входящими в соответствующие компоненты связности.

Конденсация графа не содержит кратных ребер.

Входные данные:

Первая строка содержит два натуральных числа n и m (n10000, m100000) — количество вершин и ребер графа соответственно. Каждая из следующих m строк содержит описание ребра графа. Ребро номер i описывается двумя натуральными числами [latex]b_{i}[/latex], [latex]e_{i}[/latex](1 ≤ [latex]b_{i}[/latex], [latex]e_{i}[/latex] ≤ n) — номерами начальной и конечной вершины соответственно. В графе могут присутствовать кратные ребра и петли.

Выходные данные:

Количество ребер в конденсации графа.

Тесты:

Входные данные Выходные данные
4 4 2
2 1
3 2
2 3
4 3
6 9 1
1 2
2 4
4 1
4 2
3 2
2 6
3 5
5 3
6 2

Описание решения задачи:

Компонентой сильной связности называется такое подмножество вершин C, что любые две вершины этого подмножества достижимы друг из друга. Отсюда следует, что конденсация это граф, получаемый из исходного графа сжатием каждой компоненты сильной связности в одну вершину. Отсюда имеем структуру [latex]vertex[/latex]. Основным фундаментом данного алгоритма является следующая теорема: Пусть [latex]C[/latex] и [latex]{C}'[/latex] — две различные компоненты сильной связности, и пусть в графе конденсации между ними есть ребро ([latex]C[/latex],[latex]C'[/latex]). Тогда время выхода из [latex]C[/latex] будет больше, чем время выхода из [latex]{C}'[/latex]. Базируясь на этом, выполним серию обходов в глубину с помощью функции [latex]dfs[/latex] _ [latex]g[/latex], посещая весь граф. С визитом всех вершин графа,запоминаем для каждой время выхода, записывая это в созданный [latex]list[/latex]. Далее строится транспонированный граф. Запускаем серию обходов в глубину(функция [latex]dfs[/latex] _ [latex]tg[/latex]) этого графа в порядке, определяемом списком [latex]list[/latex] (а именно, в обратном порядке, т.е. в порядке уменьшения времени выхода). Каждое множество вершин, достигнутое в результате рекурсивного запуска обхода, и будет очередной компонентой сильной связности. Окрасим все вершины каждой сильной компоненты связности в один уникальный цвет, для этого зададим в структуре параметр [latex]colour[/latex]. Число цветов окраски будет равно количеству компонент сильной связности. Далее перебираем все ребра исходного графа. Если ребро соединяет вершины разного цвета, то оно принадлежит конденсации графа. Для каждого ребра ([latex]a[/latex], [latex]b[/latex]), для которого [latex]components[a].colour[/latex] [latex]≠[/latex] [latex]components[b].colour[/latex], занесем во множество [latex]ribs[/latex] данную пару. Количество элементов во множестве [latex]ribs[/latex] будет равняться числу ребер в конденсации графа.

Условие задачи
Код задачи на с++
Засчитанное решение на e-olymp

Related Images:

6130. Дек неограниченного размера

Условие задачи:
Реализуйте структуру данных «дек». Напишите программу, содержащую описание дека и моделирующую работу дека, реализовав все указанные здесь методы. Программа считывает последовательность команд и в зависимости от команды выполняет ту или иную операцию. После выполнения каждой команды программа должна вывести одну строчку. Возможные команды для программы:

push_front

Добавить (положить) в начало дека новый элемент. Программа должна вывести ok.

push_back

Добавить (положить) в конец дека новый элемент. Программа должна вывести ok.

pop_front

Извлечь из дека первый элемент. Программа должна вывести его значение.

pop_back

Извлечь из дека последний элемент. Программа должна вывести его значение.

front

Узнать значение первого элемента (не удаляя его). Программа должна вывести его значение.

back

Узнать значение последнего элемента (не удаляя его). Программа должна вывести его значение.

size

Вывести количество элементов в деке.

clear

Очистить дек (удалить из него все элементы) и вывести ok.

exit

Программа должна вывести bye и завершить работу.

Размер дека должен быть ограничен только размером доступной оперативной памяти. Перед исполнением операций pop_front, pop_back, front, back программа должна проверять, содержится ли в деке хотя бы один элемент. Если во входных данных встречается операция pop_front, pop_back, front, back, и при этом дек пуст, то программа должна вместо числового значения вывести строку error.

Тесты

Входные данные Выходные данные
push_front 1 ok
push_back 9 ok
push_front 2 ok
push_back 3 ok
size 4
pop_front 2
pop_back 3
size 2
front 1
back 9
clear ok
size 0
back error
exit bye

Описание решения задачи:
Для решения данной задачи использовался двунаправленный линейный список. Каждый узел ДЛС содержит два поля указателей — на следующий и на предыдущий узел. Для этого в задаче была создана структура [latex]Node[/latex]. Указателем на адрес начала списка и конца, соответственно, выступают узлы [latex]head[/latex] и [latex]tail[/latex], изначально инициализированные нулем.

Я выбрала данный метод реализации неограниченного дека, так как основным назначением связного списка и является предоставление механизма для хранения и доступа к произвольному количеству данных, что являлось основным барьером решения данной задачи. В отличии от массива, подсчет размера которого так же будет требовать дополнительных математических расчетов, список не требует дополнительных временных затрат на копирование/переписывание элементов при увеличении размера массива, рассчитанного на менее громоздкие вхождения. Да, прямого доступа к значениям произвольного элемента по индексу у нас нет, но на то и была поставлена задача в реализации именно этого представителя библиотеки контейнеров, ведь в деке допустимо удаление/добавление элементов лишь на концах. Единственным действительно заметным минусом в сравнении с использованием массива, по моему мнению, является увеличение расхода памяти в три раза, из-за хранения помимо основного значения элемента указатели на предыдущий и последующий элементы.

Условие задачи
Код задачи на с++
Засчитанное решение

Related Images:

Ю 2.27. Шашечный эндшпиль

Задача из сборника задач по программированию Юркина А.Г. 2002 г.
Условие задачи:
В шашечном эндшпиле остались белая дамка и две черных пешки, позиции которых известны. Ход белых. Сможет ли дамка срубить одну или сразу обе пешки?
Continue reading

Related Images:

A322. Максимальная сумма делителей

Задача. Найти натуральное число с максимальной суммой делителей на заданном промежутке.

Входные данные:
— [latex]n[/latex] — промежуток чисел(от 1 до [latex]n[/latex]);

Выходные данные:
— [latex]max[/latex] _ [latex]sum[/latex] — максимальная сумма делителей числа на этом промежутке;
— [latex]max[/latex] _ [latex]number[/latex] — натуральное число с этой суммой;

Тесты:

[latex]n[/latex] [latex]max[/latex] _ [latex]number[/latex] [latex]max[/latex] _ [latex]sum[/latex]
100 96 252
8743 8400 30752
23000 22680 87120

Код на языке C++:

Код на языке Java:

Решение задачи:
Для нахождения суммы делителей используется функция [latex]sum[/latex] _ [latex]dividers[/latex], которая в созданном цикле сначала находит все делители числа, а после суммирует их, присваивая значение переменной [latex]sum[/latex]. Создав в главной функции [latex]main[/latex] еще один цикл со счетчиком от 1 до [latex]n[/latex], подставляю в предыдущую функцию [latex]sum[/latex] _ [latex]dividers[/latex] все натуральные числа на выбранном промежутке. C помощью свободных переменных [latex]max[/latex] _ [latex]sum[/latex] и [latex]max[/latex] _ [latex]number[/latex] нахожу максимальное значение сумм и соответствующее ему натуральное число.

Код программы на C++: Ideone
Код программы на Java: Ideone
Условия задачи(стр.134): 322

Related Images:

MS13. Решение квадратных уравнений

Условие задачи:
Каждая четвёрка чисел входного потока представляет собой квадратное уравнение в такой форме $ax^2+bx+c=d.$ Выпишите через запятую решения этих уравнений (если это возможно).

Тесты:

Входной поток чисел Корни уравнений
1 -6 8 0 1 12 20 0 2, 4; -10, -2;
1 1 -6 -2 1 -2 10 0 -2.56155, 1.56155; нет корней;
2 -0.5 2.2 0 5 0 -25 0 нет корней; -2.23607, 2.23607;

Код на языке C++:

Код на языке Java:

Решение задачи:
Для решения этой задачи используется цикл, который выполняется до тех пор, пока в потоке подряд расположены четыре числа, четыре коэффициента, которые стоят перед неизвестными в квадратном уравнении классического вида: [latex]ax^{2}\pm bx\pm c=d[/latex]. Для самого нахождения корней использовалась известная формула [latex]x_{1,2}=\frac{-b-\sqrt{b^{2} \pm 4a(c-d)}}{2a}[/latex]. В коде, для удобства, она была разделена на две части: нахождение дискриминанта [latex]D[/latex] и нахождение самих корней, что возможно (на вещественной числовой оси) лишь при условии [latex]D>0[/latex].

Решение задачи на C++: Ideone
Решение задачи на Java: Ideone

Related Images:

D2575. Сумма ряда

Условие задачи:
Найти сумму сходящегося ряда: [latex]\frac{\cos x-\cos 2x}{1}+\frac{\cos 2x -\cos 3x}{2}+\cdots+\frac{\cos nx-\cos(n+1)x}{n}+\cdots[/latex]

Входные данные:
[latex]x[/latex] — константа;
[latex]number[/latex] — номер искомой частичной суммы;

Выходные данные:
[latex]value[/latex] — значения необходимых слагаемых;
[latex]partial[/latex] _ [latex]amount[/latex] — искомая частичная сумма;

Тесты:

[latex]x[/latex] [latex]number[/latex] [latex]value[/latex] [latex]partial[/latex] _ [latex]amount[/latex]
10 3 -1.24715 0.126915 0.27373 -0.846508
100 4 0.375131 0.254642 0.167733 0.0896382 0.887145
5 5 1.12273 -0.0396918 -0.389257 -0.14578 0.16739 0.715395

Код на языке C++:

Код на языке Java:

Решение задачи:
Под словом «ряд» в математическом анализе понимают сумму бесконечного числа слагаемых. Зададим цикл с счетчиком [latex]n[/latex] от 1 до заданного пользователем числа [latex]number[/latex]. Именно такое количество необходимых слагаемых [latex]value=\frac{\cos nx -\cos (n+1)x}{n}[/latex] будет найдено на каждом шаге цикла для последующего суммирования и нахождения искомой частичной суммы.

Код задачи на C++: Ideone
Код задачи на Java: Ideone

Related Images:

KM139. Параллелограмм

Задача из журнала «Квант» №4 1972 г.
Из вершины [latex]B[/latex] параллелограмма [latex]ABCD[/latex] проведены его высоты [latex]BK[/latex] и [latex]BH[/latex]. Выразите расстояние от точки [latex]B[/latex] до точки пересечения высот треугольника [latex]BKH[/latex] через длины отрезков [latex]KH = a[/latex] и [latex]BD = b[/latex].

km139

Входные данные:
Длины отрезков [latex]a[/latex], [latex]b[/latex]

Выходные данные:
Расстояние от точки [latex]B[/latex] до точки [latex]O[/latex] — точки пересечения высот треугольника [latex]BKH[/latex] ([latex]c[/latex])

Тесты:

b a c
10 6 8
5 3 4
3 5 inf (Infinity)

Код программы на С++:

Код программы на Java:

Решение задачи:

Рассмотрим параллелограмм [latex]ABCD[/latex]. Проведем высоты [latex]BH[/latex] и [latex]BK[/latex] соответственно к сторонам [latex]AD[/latex] и [latex]DC[/latex]. Соединив точки [latex]K[/latex] и [latex]H[/latex] линией, получаем треугольник [latex]BKH[/latex]. В нем проведем три высоты [latex]BD[/latex], [latex]HM[/latex], [latex]KE[/latex] к сторонам [latex]HK[/latex], [latex]BK[/latex], [latex]HB[/latex]. Точкой пересечения высот в треугольнике является точка [latex]O[/latex].
Проведем в параллелограмме высоту [latex]DL[/latex] к стороне [latex]BC[/latex]. Соединив точки [latex]L[/latex] и [latex]K[/latex] получаем треугольник [latex]LDK[/latex]. Если сдвинуть (параллельно) треугольник [latex]BHO[/latex] так, чтобы точка [latex]H[/latex] попала в точку [latex]D[/latex], то он полностью совпадет с треугольником [latex]LKD[/latex], поскольку отрезок [latex]HO[/latex] параллелен и равен [latex]DK[/latex], а отрезок [latex]BH[/latex] параллелен и равен [latex]LD[/latex]. Следовательно, [latex]BO=LK[/latex] и два треугольника равны.
Рассмотрим прямоугольный треугольник [latex]HKL[/latex], в котором сторона [latex]HK=a[/latex] и [latex]HL=b[/latex] по условию. По теореме Пифагора отыщем сторону KL: [latex]KL=\sqrt[]{b^{2}-a^{2}}[/latex].
Так как треугольник [latex]BOH[/latex] и треугольник [latex]LKD[/latex] равны, получаем что [latex]KL=BO[/latex]

Решение задачи на C++
Решение задачи на Java

Условие задачи можно найти здесь: http://www.kvant.info/zkm_tex/zkm_main.pdf

Related Images:

ML 36. Движение катера

Задача. Катер движется по течению реки из пункта в A в пункт B и обратно с собственной скоростью [latex]v[/latex] км/час. Скорость течения постоянна — [latex]u[/latex] км/час. Расстояние между пунктами составляет [latex]s[/latex] км. Для любых неотрицательных действительных значений расстояния и скоростей вычислите время в пути.

Решение. Пусть катер движется со скоростью [latex]v[/latex] км/час, соответственно, учитывая скорость течения [latex]u[/latex] км/час, скорость катера движущегося по течению равна [latex]v+u[/latex] км/час и против течения — [latex]v-u[/latex] км/час. Используя физическую формулу [latex]t=\frac{s}{v}[/latex], где [latex]t[/latex]-время, [latex]s[/latex]-путь, [latex]v[/latex]-скорость, можем выразить время всего пути [latex]t=\frac{s}{v+u}+\frac{s}{v-u}[/latex]. Так как физическая величина [latex]t[/latex] всегда больше 0, и по математическому свойству делитель дроби не должен равняться нулю, имеем ограничение: [latex]v>u[/latex];

Решение на языке C++ имеет вид:

Тесты

Входные данные
Физические величины: v, u, s

Выходные данные
Физическая величина t

u v s t
2 2 4 inf
1 2 6 8
5 4 8 inf

Решение на ideone.

Related Images: