import random
import time
import sys
sys.setrecursionlimit(10000)
# ------------------------
# Генерація поля
# 0 = поле ('.'), 1 = камінь ('#')
# ------------------------
def generate_field(N, M, p):
grid = [[1 if random.random() < p else 0 for _ in range(M)] for _ in range(N)]
grid[N-1][0] = 0
grid[0][M-1] = 0
return grid
from collections import deque
def exists_path_bfs(grid):
N, M = len(grid), len(grid[0])
start = (N-1,0)
goal = (0, M-1)
if grid[start[0]][start[1]] != 0 or grid[goal[0]][goal[1]] != 0:
return False
q = deque([start])
vis = [[False]*M for _ in range(N)]
vis[start[0]][start[1]] = True
dirs = [(1,0),(-1,0),(0,1),(0,-1)]
while q:
r,c = q.popleft()
if (r,c) == goal:
return True
for dr,dc in dirs:
nr, nc = r+dr, c+dc
if 0 <= nr < N and 0 <= nc < M and not vis[nr][nc] and grid[nr][nc] == 0:
vis[nr][nc] = True
q.append((nr,nc))
return False
def longest_path_dfs(grid, time_limit=1.5, randomize=True):
N, M = len(grid), len(grid[0])
start = (N-1, 0)
goal = (0, M-1)
dirs = [(1,0), (0,1), (-1,0), (0,-1)]
best_path = None
best_len = -1
start_time = time.time()
max_nodes = 10**6
nodes = 0
import random as _rnd
visited = [[False]*M for _ in range(N)]
path = []
def dfs(r,c):
nonlocal best_len, best_path, nodes
if time.time() - start_time > time_limit:
return
nodes += 1
if nodes > max_nodes:
return
if (r,c) == goal:
if len(path) > best_len:
best_len = len(path)
best_path = path.copy()
return
neighs = []
for dr,dc in dirs:
nr, nc = r+dr, c+dc
if 0 <= nr < N and 0 <= nc < M and not visited[nr][nc] and grid[nr][nc] == 0:
dist = abs(nr - goal[0]) + abs(nc - goal[1])
neighs.append((dist, nr, nc))
neighs.sort(reverse=True, key=lambda x: x[0])
if randomize:
i = 0
while i < len(neighs):
j = i
while j < len(neighs) and neighs[j][0] == neighs[i][0]:
j += 1
block = neighs[i:j]
_rnd.shuffle(block)
neighs[i:j] = block
i = j
for _, nr, nc in neighs:
if time.time() - start_time > time_limit:
return
visited[nr][nc] = True
path.append((nr,nc))
dfs(nr,nc)
path.pop()
visited[nr][nc] = False
if grid[start[0]][start[1]] != 0 or grid[goal[0]][goal[1]] != 0:
return None
visited[start[0]][start[1]] = True
path.append(start)
dfs(start[0], start[1])
visited[start[0]][start[1]] = False
path.pop()
return best_path
def print_board_numbered(grid, path):
N, M = len(grid), len(grid[0])
step = {}
if path:
for i, cell in enumerate(path):
step[cell] = i
max_step = max(step.values()) if step else 0
width = max(3, len(str(max_step)) + 2)
def cell_str(s):
return str(s).center(width)
print()
for r in range(N):
row_cells = []
for c in range(M):
if (r,c) in step:
row_cells.append(cell_str(step[(r,c)]))
elif grid[r][c] == 1:
row_cells.append(cell_str("#"))
else:
row_cells.append(cell_str("."))
print("".join(row_cells))
print()
def main():
print("=== Поля і каміння — пошук довгого простого шляху")
try:
N = int(input("Введіть кількість рядків N (1..100): ").strip())
M = int(input("Введіть кількість стовпців M (1..100): ").strip())
except Exception:
print("Некоректні N або M.")
return
if not (1 <= N <= 100 and 1 <= M <= 100):
print("N і M повинні бути від 1 до 100.")
return
try:
p = float(input("Ймовірність каменю в клітинці (0..1), наприклад 0.25: ").strip())
if not (0.0 <= p <= 1.0):
raise ValueError()
except Exception:
print("Некоректне p — використовую 0.25")
p = 0.25
try:
tlim = float(input("Часовий ліміт пошуку в секундах (наприклад 1.5): ").strip())
if tlim <= 0:
tlim = 1.5
except Exception:
tlim = 1.5
regen = input("Якщо потрібно — згенерувати поле заново, якщо шляху немає? (т/н) [т]: ").strip().lower()
regen_flag = (regen == "" or regen == "т" or regen == "y" or regen == "yes")
attempts = 0
while True:
attempts += 1
grid = generate_field(N, M, p)
if exists_path_bfs(grid):
break
if not regen_flag:
break
if attempts > 2000:
print("Не вдалось згенерувати поле з шляхом за багато спроб. Спробуйте змінити p.")
return
print("\nЗгенероване поле (вирівняне):")
print_board_numbered(grid, None)
if not exists_path_bfs(grid):
print("Шляху немає — завершую.")
return
print(f"Починаємо пошук найдовшого простого шляху (таймаут = {tlim} сек)...")
best = longest_path_dfs(grid, time_limit=tlim, randomize=True)
if not best:
print("Не знайдено жодного шляху (неочікувано).")
return
print(f"Знайдений шлях довжиною {len(best)} (0 = старт).")
print("\nКарта з пронумерованим шляхом:")
print_board_numbered(grid, best)
print("\nКроки шляху (1-based координати):")
print([(r+1, c+1) for (r,c) in best])
if __name__ == "__main__":
main()
aW1wb3J0IHJhbmRvbQppbXBvcnQgdGltZQppbXBvcnQgc3lzCgpzeXMuc2V0cmVjdXJzaW9ubGltaXQoMTAwMDApCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojINCT0LXQvdC10YDQsNGG0ZbRjyDQv9C+0LvRjwojIDAgPSDQv9C+0LvQtSAoJy4nKSwgMSA9INC60LDQvNGW0L3RjCAoJyMnKQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpkZWYgZ2VuZXJhdGVfZmllbGQoTiwgTSwgcCk6CiAgICBncmlkID0gW1sxIGlmIHJhbmRvbS5yYW5kb20oKSA8IHAgZWxzZSAwIGZvciBfIGluIHJhbmdlKE0pXSBmb3IgXyBpbiByYW5nZShOKV0KICAgIGdyaWRbTi0xXVswXSA9IDAgCiAgICBncmlkWzBdW00tMV0gPSAwIAogICAgcmV0dXJuIGdyaWQKCgpmcm9tIGNvbGxlY3Rpb25zIGltcG9ydCBkZXF1ZQpkZWYgZXhpc3RzX3BhdGhfYmZzKGdyaWQpOgogICAgTiwgTSA9IGxlbihncmlkKSwgbGVuKGdyaWRbMF0pCiAgICBzdGFydCA9IChOLTEsMCkKICAgIGdvYWwgPSAoMCwgTS0xKQogICAgaWYgZ3JpZFtzdGFydFswXV1bc3RhcnRbMV1dICE9IDAgb3IgZ3JpZFtnb2FsWzBdXVtnb2FsWzFdXSAhPSAwOgogICAgICAgIHJldHVybiBGYWxzZQogICAgcSA9IGRlcXVlKFtzdGFydF0pCiAgICB2aXMgPSBbW0ZhbHNlXSpNIGZvciBfIGluIHJhbmdlKE4pXQogICAgdmlzW3N0YXJ0WzBdXVtzdGFydFsxXV0gPSBUcnVlCiAgICBkaXJzID0gWygxLDApLCgtMSwwKSwoMCwxKSwoMCwtMSldCiAgICB3aGlsZSBxOgogICAgICAgIHIsYyA9IHEucG9wbGVmdCgpCiAgICAgICAgaWYgKHIsYykgPT0gZ29hbDoKICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICBmb3IgZHIsZGMgaW4gZGlyczoKICAgICAgICAgICAgbnIsIG5jID0gcitkciwgYytkYwogICAgICAgICAgICBpZiAwIDw9IG5yIDwgTiBhbmQgMCA8PSBuYyA8IE0gYW5kIG5vdCB2aXNbbnJdW25jXSBhbmQgZ3JpZFtucl1bbmNdID09IDA6CiAgICAgICAgICAgICAgICB2aXNbbnJdW25jXSA9IFRydWUKICAgICAgICAgICAgICAgIHEuYXBwZW5kKChucixuYykpCiAgICByZXR1cm4gRmFsc2UKCmRlZiBsb25nZXN0X3BhdGhfZGZzKGdyaWQsIHRpbWVfbGltaXQ9MS41LCByYW5kb21pemU9VHJ1ZSk6CiAgICBOLCBNID0gbGVuKGdyaWQpLCBsZW4oZ3JpZFswXSkKICAgIHN0YXJ0ID0gKE4tMSwgMCkKICAgIGdvYWwgPSAoMCwgTS0xKQogICAgZGlycyA9IFsoMSwwKSwgKDAsMSksICgtMSwwKSwgKDAsLTEpXSAgCiAgICBiZXN0X3BhdGggPSBOb25lCiAgICBiZXN0X2xlbiA9IC0xCiAgICBzdGFydF90aW1lID0gdGltZS50aW1lKCkKICAgIG1heF9ub2RlcyA9IDEwKio2CiAgICBub2RlcyA9IDAKCiAgICBpbXBvcnQgcmFuZG9tIGFzIF9ybmQKCiAgICB2aXNpdGVkID0gW1tGYWxzZV0qTSBmb3IgXyBpbiByYW5nZShOKV0KICAgIHBhdGggPSBbXQoKICAgIGRlZiBkZnMocixjKToKICAgICAgICBub25sb2NhbCBiZXN0X2xlbiwgYmVzdF9wYXRoLCBub2RlcwogICAgICAgIGlmIHRpbWUudGltZSgpIC0gc3RhcnRfdGltZSA+IHRpbWVfbGltaXQ6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIG5vZGVzICs9IDEKICAgICAgICBpZiBub2RlcyA+IG1heF9ub2RlczoKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgIGlmIChyLGMpID09IGdvYWw6CiAgICAgICAgICAgIGlmIGxlbihwYXRoKSA+IGJlc3RfbGVuOgogICAgICAgICAgICAgICAgYmVzdF9sZW4gPSBsZW4ocGF0aCkKICAgICAgICAgICAgICAgIGJlc3RfcGF0aCA9IHBhdGguY29weSgpCiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBuZWlnaHMgPSBbXQogICAgICAgIGZvciBkcixkYyBpbiBkaXJzOgogICAgICAgICAgICBuciwgbmMgPSByK2RyLCBjK2RjCiAgICAgICAgICAgIGlmIDAgPD0gbnIgPCBOIGFuZCAwIDw9IG5jIDwgTSBhbmQgbm90IHZpc2l0ZWRbbnJdW25jXSBhbmQgZ3JpZFtucl1bbmNdID09IDA6CiAgICAgICAgICAgICAgICBkaXN0ID0gYWJzKG5yIC0gZ29hbFswXSkgKyBhYnMobmMgLSBnb2FsWzFdKQogICAgICAgICAgICAgICAgbmVpZ2hzLmFwcGVuZCgoZGlzdCwgbnIsIG5jKSkKICAgICAgICBuZWlnaHMuc29ydChyZXZlcnNlPVRydWUsIGtleT1sYW1iZGEgeDogeFswXSkKICAgICAgICBpZiByYW5kb21pemU6CiAgICAgICAgICAgIGkgPSAwCiAgICAgICAgICAgIHdoaWxlIGkgPCBsZW4obmVpZ2hzKToKICAgICAgICAgICAgICAgIGogPSBpCiAgICAgICAgICAgICAgICB3aGlsZSBqIDwgbGVuKG5laWdocykgYW5kIG5laWdoc1tqXVswXSA9PSBuZWlnaHNbaV1bMF06CiAgICAgICAgICAgICAgICAgICAgaiArPSAxCiAgICAgICAgICAgICAgICBibG9jayA9IG5laWdoc1tpOmpdCiAgICAgICAgICAgICAgICBfcm5kLnNodWZmbGUoYmxvY2spCiAgICAgICAgICAgICAgICBuZWlnaHNbaTpqXSA9IGJsb2NrCiAgICAgICAgICAgICAgICBpID0gagoKICAgICAgICBmb3IgXywgbnIsIG5jIGluIG5laWdoczoKICAgICAgICAgICAgaWYgdGltZS50aW1lKCkgLSBzdGFydF90aW1lID4gdGltZV9saW1pdDoKICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICB2aXNpdGVkW25yXVtuY10gPSBUcnVlCiAgICAgICAgICAgIHBhdGguYXBwZW5kKChucixuYykpCiAgICAgICAgICAgIGRmcyhucixuYykKICAgICAgICAgICAgcGF0aC5wb3AoKQogICAgICAgICAgICB2aXNpdGVkW25yXVtuY10gPSBGYWxzZQogICAgaWYgZ3JpZFtzdGFydFswXV1bc3RhcnRbMV1dICE9IDAgb3IgZ3JpZFtnb2FsWzBdXVtnb2FsWzFdXSAhPSAwOgogICAgICAgIHJldHVybiBOb25lCgogICAgdmlzaXRlZFtzdGFydFswXV1bc3RhcnRbMV1dID0gVHJ1ZQogICAgcGF0aC5hcHBlbmQoc3RhcnQpCiAgICBkZnMoc3RhcnRbMF0sIHN0YXJ0WzFdKQogICAgdmlzaXRlZFtzdGFydFswXV1bc3RhcnRbMV1dID0gRmFsc2UKICAgIHBhdGgucG9wKCkKCiAgICByZXR1cm4gYmVzdF9wYXRoCgpkZWYgcHJpbnRfYm9hcmRfbnVtYmVyZWQoZ3JpZCwgcGF0aCk6CiAgICBOLCBNID0gbGVuKGdyaWQpLCBsZW4oZ3JpZFswXSkKICAgIHN0ZXAgPSB7fQogICAgaWYgcGF0aDoKICAgICAgICBmb3IgaSwgY2VsbCBpbiBlbnVtZXJhdGUocGF0aCk6CiAgICAgICAgICAgIHN0ZXBbY2VsbF0gPSBpCgogICAgbWF4X3N0ZXAgPSBtYXgoc3RlcC52YWx1ZXMoKSkgaWYgc3RlcCBlbHNlIDAKICAgIHdpZHRoID0gbWF4KDMsIGxlbihzdHIobWF4X3N0ZXApKSArIDIpCgogICAgZGVmIGNlbGxfc3RyKHMpOgogICAgICAgIHJldHVybiBzdHIocykuY2VudGVyKHdpZHRoKQoKICAgIHByaW50KCkKICAgIGZvciByIGluIHJhbmdlKE4pOgogICAgICAgIHJvd19jZWxscyA9IFtdCiAgICAgICAgZm9yIGMgaW4gcmFuZ2UoTSk6CiAgICAgICAgICAgIGlmIChyLGMpIGluIHN0ZXA6CiAgICAgICAgICAgICAgICByb3dfY2VsbHMuYXBwZW5kKGNlbGxfc3RyKHN0ZXBbKHIsYyldKSkKICAgICAgICAgICAgZWxpZiBncmlkW3JdW2NdID09IDE6CiAgICAgICAgICAgICAgICByb3dfY2VsbHMuYXBwZW5kKGNlbGxfc3RyKCIjIikpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICByb3dfY2VsbHMuYXBwZW5kKGNlbGxfc3RyKCIuIikpCiAgICAgICAgcHJpbnQoIiIuam9pbihyb3dfY2VsbHMpKQogICAgcHJpbnQoKQpkZWYgbWFpbigpOgogICAgcHJpbnQoIj09PSDQn9C+0LvRjyDRliDQutCw0LzRltC90L3RjyDigJQg0L/QvtGI0YPQuiDQtNC+0LLQs9C+0LPQviDQv9GA0L7RgdGC0L7Qs9C+INGI0LvRj9GF0YMiKQogICAgdHJ5OgogICAgICAgIE4gPSBpbnQoaW5wdXQoItCS0LLQtdC00ZbRgtGMINC60ZbQu9GM0LrRltGB0YLRjCDRgNGP0LTQutGW0LIgTiAoMS4uMTAwKTogIikuc3RyaXAoKSkKICAgICAgICBNID0gaW50KGlucHV0KCLQktCy0LXQtNGW0YLRjCDQutGW0LvRjNC60ZbRgdGC0Ywg0YHRgtC+0LLQv9GG0ZbQsiBNICgxLi4xMDApOiAiKS5zdHJpcCgpKQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICBwcmludCgi0J3QtdC60L7RgNC10LrRgtC90ZYgTiDQsNCx0L4gTS4iKQogICAgICAgIHJldHVybgogICAgaWYgbm90ICgxIDw9IE4gPD0gMTAwIGFuZCAxIDw9IE0gPD0gMTAwKToKICAgICAgICBwcmludCgiTiDRliBNINC/0L7QstC40L3QvdGWINCx0YPRgtC4INCy0ZbQtCAxINC00L4gMTAwLiIpCiAgICAgICAgcmV0dXJuCgogICAgdHJ5OgogICAgICAgIHAgPSBmbG9hdChpbnB1dCgi0JnQvNC+0LLRltGA0L3RltGB0YLRjCDQutCw0LzQtdC90Y4g0LIg0LrQu9GW0YLQuNC90YbRliAoMC4uMSksINC90LDQv9GA0LjQutC70LDQtCAwLjI1OiAiKS5zdHJpcCgpKQogICAgICAgIGlmIG5vdCAoMC4wIDw9IHAgPD0gMS4wKToKICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcigpCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgIHByaW50KCLQndC10LrQvtGA0LXQutGC0L3QtSBwIOKAlCDQstC40LrQvtGA0LjRgdGC0L7QstGD0Y4gMC4yNSIpCiAgICAgICAgcCA9IDAuMjUKCiAgICB0cnk6CiAgICAgICAgdGxpbSA9IGZsb2F0KGlucHV0KCLQp9Cw0YHQvtCy0LjQuSDQu9GW0LzRltGCINC/0L7RiNGD0LrRgyDQsiDRgdC10LrRg9C90LTQsNGFICjQvdCw0L/RgNC40LrQu9Cw0LQgMS41KTogIikuc3RyaXAoKSkKICAgICAgICBpZiB0bGltIDw9IDA6CiAgICAgICAgICAgIHRsaW0gPSAxLjUKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgdGxpbSA9IDEuNQoKICAgIHJlZ2VuID0gaW5wdXQoItCv0LrRidC+INC/0L7RgtGA0ZbQsdC90L4g4oCUINC30LPQtdC90LXRgNGD0LLQsNGC0Lgg0L/QvtC70LUg0LfQsNC90L7QstC+LCDRj9C60YnQviDRiNC70Y/RhdGDINC90LXQvNCw0ZQ/ICjRgi/QvSkgW9GCXTogIikuc3RyaXAoKS5sb3dlcigpCiAgICByZWdlbl9mbGFnID0gKHJlZ2VuID09ICIiIG9yIHJlZ2VuID09ICLRgiIgb3IgcmVnZW4gPT0gInkiIG9yIHJlZ2VuID09ICJ5ZXMiKQoKICAgIGF0dGVtcHRzID0gMAogICAgd2hpbGUgVHJ1ZToKICAgICAgICBhdHRlbXB0cyArPSAxCiAgICAgICAgZ3JpZCA9IGdlbmVyYXRlX2ZpZWxkKE4sIE0sIHApCiAgICAgICAgaWYgZXhpc3RzX3BhdGhfYmZzKGdyaWQpOgogICAgICAgICAgICBicmVhawogICAgICAgIGlmIG5vdCByZWdlbl9mbGFnOgogICAgICAgICAgICBicmVhawogICAgICAgIGlmIGF0dGVtcHRzID4gMjAwMDoKICAgICAgICAgICAgcHJpbnQoItCd0LUg0LLQtNCw0LvQvtGB0Ywg0LfQs9C10L3QtdGA0YPQstCw0YLQuCDQv9C+0LvQtSDQtyDRiNC70Y/RhdC+0Lwg0LfQsCDQsdCw0LPQsNGC0L4g0YHQv9GA0L7QsS4g0KHQv9GA0L7QsdGD0LnRgtC1INC30LzRltC90LjRgtC4IHAuIikKICAgICAgICAgICAgcmV0dXJuCgogICAgcHJpbnQoIlxu0JfQs9C10L3QtdGA0L7QstCw0L3QtSDQv9C+0LvQtSAo0LLQuNGA0ZbQstC90Y/QvdC1KToiKQogICAgcHJpbnRfYm9hcmRfbnVtYmVyZWQoZ3JpZCwgTm9uZSkKCiAgICBpZiBub3QgZXhpc3RzX3BhdGhfYmZzKGdyaWQpOgogICAgICAgIHByaW50KCLQqNC70Y/RhdGDINC90LXQvNCw0ZQg4oCUINC30LDQstC10YDRiNGD0Y4uIikKICAgICAgICByZXR1cm4KCiAgICBwcmludChmItCf0L7Rh9C40L3QsNGU0LzQviDQv9C+0YjRg9C6INC90LDQudC00L7QstGI0L7Qs9C+INC/0YDQvtGB0YLQvtCz0L4g0YjQu9GP0YXRgyAo0YLQsNC50LzQsNGD0YIgPSB7dGxpbX0g0YHQtdC6KS4uLiIpCiAgICBiZXN0ID0gbG9uZ2VzdF9wYXRoX2RmcyhncmlkLCB0aW1lX2xpbWl0PXRsaW0sIHJhbmRvbWl6ZT1UcnVlKQoKICAgIGlmIG5vdCBiZXN0OgogICAgICAgIHByaW50KCLQndC1INC30L3QsNC50LTQtdC90L4g0LbQvtC00L3QvtCz0L4g0YjQu9GP0YXRgyAo0L3QtdC+0YfRltC60YPQstCw0L3QvikuIikKICAgICAgICByZXR1cm4KCiAgICBwcmludChmItCX0L3QsNC50LTQtdC90LjQuSDRiNC70Y/RhSDQtNC+0LLQttC40L3QvtGOIHtsZW4oYmVzdCl9ICgwID0g0YHRgtCw0YDRgikuIikKICAgIHByaW50KCJcbtCa0LDRgNGC0LAg0Lcg0L/RgNC+0L3Rg9C80LXRgNC+0LLQsNC90LjQvCDRiNC70Y/RhdC+0Lw6IikKICAgIHByaW50X2JvYXJkX251bWJlcmVkKGdyaWQsIGJlc3QpCgogICAgcHJpbnQoIlxu0JrRgNC+0LrQuCDRiNC70Y/RhdGDICgxLWJhc2VkINC60L7QvtGA0LTQuNC90LDRgtC4KToiKQogICAgcHJpbnQoWyhyKzEsIGMrMSkgZm9yIChyLGMpIGluIGJlc3RdKQoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIG1haW4oKQo=