Задний план
Я построил простую полосу препятствий, поместив коробки в прямоугольную комнату. Теперь я хочу подсчитать количество принципиально разных способов, которыми это можно решить. Мне нужно, чтобы ты написал мне программу для этого.
вход
Ваш ввод представляет собой непустой прямоугольный массив символов .#
. Точки .
- это пустое пространство, и они #
являются препятствиями.
Путь через препятствие курс начинается в верхнем левом углу и заканчивается в правом нижнем углу, и идет только вправо или вниз. Кроме того, действительный путь не может пройти через препятствие. Вот несколько примеров, нарисованных с помощью +
символов -characters:
Valid path Invalid path Invalid path Invalid path
++........ ++........ +++++..... ..+.......
.++++++#.. .+.....#.. ....+++#++ ..++...#..
......+#.. .+.++++#.. .......#.+ ...+++.#..
....#.++++ .+++#.++++ ....#....+ ....#+....
Два пути по существу похожи 1, если один может быть преобразован в другой, перемещаясь по одному +
за раз. Промежуточные пути также должны быть действительными, чтобы вы не могли согнуть путь над препятствием. Например, первые два пути здесь, по сути, похожи, но третий существенно отличается от них, поскольку он не может шевелиться по двум препятствиям:
++........ +......... +++++++++.
.+++++.#.. ++.....#.. .......#+.
.....+.#.. .++++++#.. .......#++
....#+++++ ....#.++++ ....#....+
Выход
Ваш вывод - это количество принципиально разных путей через полосу препятствий. Другими словами, если все действительные пути делятся на классы по существу одинаковых путей, на выходе получается количество классов. Обратите внимание, что это число может быть 0, если нет действительных путей.
Правила и оценки
Вы можете написать полную программу или функцию. Побеждает меньшее количество байтов, и стандартные лазейки запрещены. Нет ограничений по времени, за исключением того, что вы должны оценивать свою программу в каждом тестовом примере перед ее отправкой.
Контрольные примеры
....
....
.... => 1
...#
....
...# => 0
#..#
..#.
.... => 0
......
......
..##..
......
...... => 2
......
...#..
......
..#...
#..... => 3
......
..#...
......
....#.
#..... => 4
.......
##.....
....###
...#...
..##.#.
#....#.
..#.... => 0
......#.
..##....
...#....
.......#
....#...
.##...#.
....#...
##...... => 7
.........
.#.#.#.#.
.........
#.#...#.#
.........
.#.#.#.#.
......... => 17
..........
.#........
..........
.....#....
#.........
........#.
......#...
.......... => 10
.........
.#.......
.........
...#.....
.........
.....#...
.........
.......#.
......... => 16
1 Правильный технический термин - «гомотопный» .
+
в то время »? Означает ли это, что по существу одинаковые пути должны быть одинаковой длины?+
» я, по сути, имею в виду, что один угол пути инвертирован в угол противоположного направления.Ответы:
Улитки ,
5349 байтНа этот раз мне не пришлось пользоваться
t
страшной инструкцией телепорта. В результате тестовые случаи заканчиваются мгновенно, вместо того, чтобы брать эоны.Ungolfed:
Параметры
A^
означают, чтобы начать в верхнем левом углу и подсчитать все соответствующие пути. Основная идея состоит в том, чтобы проверить условие каноничности для путей. Я, честно говоря, не ожидал, что это сработает, но он прибил контрольные тесты, так что ... То, что он пытается проверить, - это то, что в текущем пути выбран самый жадный маршрут, то есть идет столько раз, сколько возможно вниз столько раз, сколько это возможно, и т.д., не пересекая любые препятствия. Это делается путем проверки, после перемещения вправо 1 или более раз, а затем вниз 1 или более раз, что следующий квадрат (который должен быть справа) не может быть достигнут, пройдя еще раз вправо в предыдущем правом сегменте. Аналогичное условие также проверяется после перемещения вправо, а затем вниз.источник
Python 2,
170131112 байтФункция,
f
принимающая полосу препятствий в виде списка строк и возвращающая количество принципиально разных путей.объяснение
Основная концепция такова: мы выбираем определенное препятствие o , чтобы в прямоугольнике, ограничивающем о и верхний левый угол , не было других препятствий .
Затем мы рассмотрим два подпотока к востоку и к югу от о . Мы рассматриваем любой из этих субкурсов только в том случае, если o действительно можно пересечь с направления, которое ведет к ним, то есть пересечь с севера, чтобы попасть на восток, и пересечь с запада, чтобы добраться до юга. Мы решаем задачу для каждого из выбранных субкурсов и возвращаем сумму результатов. Эти числа соответствуют количеству существенно разных путей при пересечении o слева и справа соответственно, поэтому два результирующих набора путей существенно различаются. Поскольку между начальной точкой и о, существует путь между начальной точкой и любой точкой входа в каждую из этих областей, и все такие пути, которые ведут к одной и той же точке, по существу похожи, следовательно, вышеупомянутая сумма представляет собой полное количество принципиально разных путей во всем курсе.
Все немного усложняется тем фактом, что одна полоса препятствий не передает всю необходимую информацию. Например, рассмотрим курс B на диаграмме выше. Взятые сами по себе, мы не можем определить, можно ли пересечь каждое из препятствий с севера. Если B был входным курсом, то, поскольку все пути начинаются в верхнем левом углу, ни одно препятствие не могло быть пересечено с севера, но, поскольку мы можем достичь B с любой стороны левого препятствия при пересечении o с востока мы должны рассматривать это препятствие так, как будто оно может быть преодолено с севера при прохождении курса; однако это не относится к правильному препятствию, которое нельзя пересечь с этого направления.
Мы получаем эту дополнительную информацию, указав вместе с полосой препятствий количество символов в первом ряду, начиная слева, с которых может начинаться путь. На диаграмме выше это обозначается сплошной линией рядом с каждым курсом. Хотя технически нам также необходимо указать соответствующее количество символов в первом столбце, с которого может начинаться путь, как в случае с подкурсом A , на практике мы всегда выбирали самое высокое препятствие, поэтому эта информация не требуется ,
Фактический выбор o выглядит следующим образом: мы делаем вид, что за каждой строкой, отличной от последней, следует препятствие (т.
#
Е. К нему добавлено), и выбираем первое препятствие в результирующем курсе в порядке чтения. Для строк (кроме последней), в которых изначально не было препятствий, это фактически означает, что мы их пропускаем (при этом отмечается, что путь ниже может начинаться с любого символа в верхней строке). В итоге мы получаем курс, в котором есть один ряд без препятствий, для которого существует только один возможный путь.источник
CJam,
858482818079 байтовПопробуйте онлайн. Или запустить весь набор тестов.
Эффективность этого решения, вероятно, довольно ужасна, но она решает каждый тестовый случай в течение нескольких секунд.
объяснение
Я должен добавить полную разбивку кода позже, но алгоритмическая идея заключается в следующем:
W
иH
соответственно.W-1
копий0
иH-1
копийW-1
(где0
представляет горизонтальный шаг иW-1
вертикальный шаг). Мы проходим все эти пути, многократно беря первый элемент сетки, а затем пропускаяstep
ячейки в порядке чтения (гдеstep
есть0
илиW-1
). Мы отбрасываем все пути, которые содержат#
.x
переместился ли один , мы проверяем, отличаются ли пути ровно в двух местах. Если это так, то в этих двух местах вертикальное и горизонтальное движение поменяются местами. Это приводит к тому, что весь сегмент между этими движениями смещается по диагонали на одну ячейку. Но если оба этих пути верны, смещение любой части пути на одну ячейку по диагонали не может пересечь препятствие, поэтому они похожи. Нам все еще нужно найти транзитивное замыкание, поэтому мы продолжаем делать это до тех пор, пока не найдем больше похожих путей, прежде чем перейти к следующей группе.источник