import random import time import sys sys.setrecursionlimit(10000) 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()
20 20 0.25 1.5 т
=== Поля і каміння — пошук довгого простого шляху Введіть кількість рядків N (1..100): Введіть кількість стовпців M (1..100): Ймовірність каменю в клітинці (0..1), наприклад 0.25: Часовий ліміт пошуку в секундах (наприклад 1.5): Якщо потрібно — регенерувати поле поки існує шлях? (т/н) [т]: Згенероване поле (вирівняне): . # . . . # # . . # # . . . # . . # . . # . . . # . . . # # # . . . . . # . . . . . . # . . . . . . . . . . . . . . . . . . # . # . # . . . . # . # . . . # . . . . # . . . . . . . . . # . . # # . . . . # . # # . . # . . # . # . . . . . . . . . # . . . . . # . . . . . . # . # . # # . . # . . . . # # . . . . . . # . . . . # . . # . . # . . . . . . . # . # # . . . # . # . . . . . . # . . . . . . # . . . . . . . . . . # . . . . . # . . # . . # . . # . . . . . # # . # . # . # . . . # . # . . . # . . . # # . . . . # . . # . . # . . . # . . # # . . . . . # # # . . . . # . . . # . # . . . . . . . . . . . # . . . . . . . . . # . . . # . # # . . . . . # . . . . . . . . # # # . . # . . # . # # . . . . . . . . . . # . . . . # # . # . # . . . . . . . . # . # . . . # . . # . . # . . . # . . . . . # # . Починаємо пошук найдовшого простого шляху (таймаут = 1.5 сек)... Знайдений шлях довжиною 167 (0 = старт). Карта з пронумерованим шляхом: . # . . . # # . . # # 134 135 136 # . . # 165 166 # . . . # . . . # # # 133 132 137 140 141 # 163 164 . . . . # . . . . . 128 129 130 131 138 139 142 143 162 161 160 . . # . # . # 99 100 127 . # . # 146 145 144 # 158 159 . . # . . 96 97 98 101 126 125 124 # 148 147 # # . 157 156 . # . # # 95 94 # 102 103 # 123 # 149 150 151 152 153 154 155 . . # . 91 92 93 . # 104 105 122 121 120 119 # . # . # # . . # 90 89 . . # # 106 109 110 117 118 . # . . . . # . . # 88 . # . . 107 108 111 116 115 # . # # . . . # . # 87 86 . 80 79 78 # 112 113 114 . . . # . . . 17 18 19 20 85 . 81 # 77 76 75 74 73 # . . # . . # 16 . # 21 84 83 82 . # # . # 72 # . # . . . # 15 # . 22 . # . . . # # . 71 70 . # . . # . 14 # . 23 . # . . # # 62 63 64 69 . # # # 5 6 13 12 # 24 . . # . # . 61 60 65 68 . . . . 4 7 # 11 . 25 26 41 42 43 . . # 59 66 67 # . # # 3 8 9 10 . # 27 40 39 44 45 46 57 58 # # # . . # 2 . # . # # 28 29 38 37 36 47 56 55 54 . # . . . 1 # # . # . # 30 31 34 35 48 49 52 53 # . # . . 0 # . . # . . # 32 33 . # 50 51 . . . # # . Кроки шляху (1-based координати): [(20, 1), (19, 1), (18, 1), (17, 1), (16, 1), (15, 1), (15, 2), (16, 2), (17, 2), (17, 3), (17, 4), (16, 4), (15, 4), (15, 3), (14, 3), (13, 3), (12, 3), (11, 3), (11, 4), (11, 5), (11, 6), (12, 6), (13, 6), (14, 6), (15, 6), (16, 6), (16, 7), (17, 7), (18, 7), (18, 8), (19, 8), (19, 9), (20, 9), (20, 10), (19, 10), (19, 11), (18, 11), (18, 10), (18, 9), (17, 9), (17, 8), (16, 8), (16, 9), (16, 10), (17, 10), (17, 11), (17, 12), (18, 12), (19, 12), (19, 13), (20, 13), (20, 14), (19, 14), (19, 15), (18, 15), (18, 14), (18, 13), (17, 13), (17, 14), (16, 14), (15, 14), (15, 13), (14, 13), (14, 14), (14, 15), (15, 15), (16, 15), (16, 16), (15, 16), (14, 16), (13, 16), (13, 15), (12, 15), (11, 15), (11, 14), (11, 13), (11, 12), (11, 11), (10, 11), (10, 10), (10, 9), (11, 9), (12, 9), (12, 8), (12, 7), (11, 7), (10, 7), (10, 6), (9, 6), (8, 6), (8, 5), (7, 5), (7, 6), (7, 7), (6, 7), (6, 6), (5, 6), (5, 7), (5, 8), (4, 8), (4, 9), (5, 9), (6, 9), (6, 10), (7, 10), (7, 11), (8, 11), (9, 11), (9, 12), (8, 12), (8, 13), (9, 13), (10, 13), (10, 14), (10, 15), (9, 15), (9, 14), (8, 14), (8, 15), (7, 15), (7, 14), (7, 13), (7, 12), (6, 12), (5, 12), (5, 11), (5, 10), (4, 10), (3, 10), (3, 11), (3, 12), (3, 13), (2, 13), (2, 12), (1, 12), (1, 13), (1, 14), (2, 14), (3, 14), (3, 15), (2, 15), (2, 16), (3, 16), (3, 17), (4, 17), (4, 16), (4, 15), (5, 15), (5, 14), (6, 14), (6, 15), (6, 16), (6, 17), (6, 18), (6, 19), (6, 20), (5, 20), (5, 19), (4, 19), (4, 20), (3, 20), (3, 19), (3, 18), (2, 18), (2, 19), (1, 19), (1, 20)]