При закрытии подписчики были переданы в рассылку "Обзор инструментов 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 |
Отписаться
Убрать рекламу |
| В избранное | ||