При закрытии подписчики были переданы в рассылку "Обзор инструментов SEO-оптимизатора и методов продвижения" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Информационный Канал Subscribe.Ru |
Олимпиадные задачи и алгоритмы на C++Здравствуйте, уважаемые подписчики.
Решение задачи №5 "Лабиринт с минами" (7 баллов).Решение основано, как вы догадались, на волне. В описанный ранее алгоритм необходимо добавить вычисление для каждой клетки количества кратчайших путей до нее и количества безопасных кратчайших путей. Под безопасным путей понимается путь без мин. Ответом к задаче является отношение числа безопасных путей до конечной клетки к общему числу путей. Как вычислить число путей до клетки? Это сумма количества путей до соседних с ней клеток, расстояние до которых на единицу меньше расстояния до данной клетки. Если в данной клетке расположена мина, то число безопасных путей до нее 0, иначе это сумма числа безопасных путей до соседних с ней клеток, расстояние до которых на единицу меньше. Есть другой вариант решения. Найти волной расстояние до каждой клетки. Затем перебором искать общее количество путей и количество безопасных путей из начальной клетки в конечную. Такой алгоритм не укладывается в ограничения по времени на 19 тесте. В нем на поле 15 на 15 начальная и конечная клетки расположены в двух противоположных угловых клетках. Текст программы: #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); int n, m, si, sj, fi, fj, i, j; char lab[15][16]; long total[15][15]; // для хранения числа путей в клетку long good[15][15]; // для хранения числа безопасных путей в клетку scanf("%d%d", &n, &m); for (i = 0; i < n; i++) scanf("%s", lab[i]); for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (lab[i][j] == 's') si = i, sj = j; else if (lab[i][j] == 'f') fi = i, fj = j; // ------------ ПОИСК В ШИРИНУ ------------------------------------- // lab - двухмерный массив, в котором хранится лабиринт // n,m - количество строк и столбцов в массиве lab // si,sj - начальная позиция // fi,fj - конечная позиция typedef struct point {int i, j;} point; int di[4] = { -1, 0, 1, 0}; int dj[4] = { 0, 1, 0, -1}; int d[15][15]; // массив расстояний int head,tail; // указатели очереди point queue[15*15]; // очередь // обнуляем массив расстояний for (i = 0; i < n; i++) for (j = 0; j < m; j++) d[i][j] = 0; d[si][sj] = 1; // расстояние до начальной клетки равно 1 // инициализируем очередь head = tail = 0; queue[tail].i = si; queue[tail++].j = sj; // заносим в очередь начальную клетку while (head < tail) // цикл пока очередь не пуста { point p = queue[head++]; // берем следующую позицию из очереди // --- Дополнительный код добавлен сюда ---- // вычисление количества путей до текущей клетки p if (p.i == si && p.j == sj) { total[si][sj] = 1; good[si][sj] = 1; } else { total[p.i][p.j] = 0; good[p.i][p.j] = 0; for (int k = 0; k < 4; k++) { point newp; newp.i = p.i + di[k]; newp.j = p.j + dj[k]; if (0 <= newp.i && newp.i < n && 0 <= newp.j && newp.j <= m) if (d[newp.i][newp.j] == d[p.i][p.j] - 1) { total[p.i][p.j] += total[p.i + di[k]][p.j + dj[k]]; good[p.i][p.j] += good[p.i + di[k]][p.j + dj[k]]; } } if (lab[p.i][p.j] == 'm') good[p.i][p.j] = 0; } // ----------------------------------------- for (int k = 0; k < 4; k++) // цикл по соседним клеткам { point newp; newp.i = p.i + di[k]; newp.j = p.j + dj[k]; // проверяем, что такая клетка есть if (0 <= newp.i && newp.i < n && 0 <= newp.j && newp.j < m) // проверяем, что она свободна и ранее ее не посещали if (lab[newp.i][newp.j] != '#' && d[newp.i][newp.j] == 0) { d[newp.i][newp.j] = d[p.i][p.j] + 1; // находим расстояние queue[tail++] = newp; // заносим позицию в очередь } } } // ----------------------------------------------------------------- printf("%.4lf\n", (double)good[fi][fj] / total[fi][fj]); fclose(stdout); return 0; } Результаты по задаче №5 "Лабиринт с минами" (7 баллов).
Решение задачи №6 "Бактерии" (8 баллов).Большинство присланных программ решают задачу "в лоб". Они хранят массив из N элементов и проводят над ним T преобразований. Такое решение проходит лишь при малых значениях T. При T порядка миллиарда оно работает слишком медленно и не укладывается в ограничение по времени. На самом деле эта задача решается с помощью линейной алгебры. Представим состояние колоний в виде вектора-столбца из N элементов. Тогда каждое из преобразований можно представить как домножение данного вектора на некоторую матрицу размера N на N слева. Рассмотрим пример для N = 4. die 2 0 reproduce 0 3 swap 1 3 merry-go-round 0 0 |1 0 0 0| |3 0 0 0| |1 0 0 0| |0 0 0 1| |0 1 0 0| |0 1 0 0| |0 0 0 1| |1 0 0 0| |0 0 0 0| |0 0 1 0| |0 0 1 0| |0 1 0 0| |0 0 0 1| |0 0 0 1| |0 1 0 0| |0 0 1 0| Пусть в четырех колониях следующее число бактерий: 3, 1, 2, 0. Применение правила merry-go-round соответствует следующему произведению: |0 0 0 1| |3| |0| |1 0 0 0| * |1| = |3| |0 1 0 0| |2| |1| |0 0 1 0| |0| |2| Как использование матриц может ускорить вычисление? Обозначим матрицы, соответствующие M заданным преобразованиям, через P(0), P(1), ..., P(M-1). Начальный (единичный) вектор-столбец обозначим I. Тогда вектор-столбец после всех выполненных преобразований будет следующим: (P(0)*P(1)*...*P(M-1))*...*(P(0)*P(1)*...*P(M-1))*P(0)*P(1)*...*P(T%M-1)*I Если мы обозначим P(0)*P(1)*...*P(M-1) через Q, то получим: (Q^(T/M))*P(0)*P(1)*...*P(T%M-1)*I Вычисление матриц Q можно выполнить за M-1 операцию перемножения матриц. Сложность перемножения матриц N на N равна O(N^3), значит сложность вычисления Q есть O(M * N^3). Далее Q возводится в степень T/M. Эту операцию можно выполнить за время O(log(T/M) * N^3). И еще T%M перемножений матриц добавляет O(T%M * N^3). В итоге сложность алгоритма получается O(M * N^3 + log(T/M) * N^3 + T%M * N^3) = O(M * N^3). Заметим, что все вычисления производятся по модулю k. Никаких переполнений при вычислении заданных матриц возникнуть не должно. Полученную матрицу итогового преобразования необходимо умножить на единичный вектор-столбец. Полученный вектор-столбец и будет ответом. Текст программы: #include Результаты по задаче №6 "Бактерии" (8 баллов).
Условия задач, тесты и решения вы всегда можете найти на сайте accepted.narod.ru. Ведущий рассылкой: Виктор Журавлев |
http://subscribe.ru/
E-mail: ask@subscribe.ru |
Отписаться
Убрать рекламу |
В избранное | ||