結果
問題 |
No.228 ゆきこちゃんの 15 パズル
|
ユーザー |
![]() |
提出日時 | 2025-06-12 16:35:42 |
言語 | PyPy3 (7.3.15) |
結果 |
WA
|
実行時間 | - |
コード長 | 3,967 bytes |
コンパイル時間 | 260 ms |
コンパイル使用メモリ | 82,116 KB |
実行使用メモリ | 56,728 KB |
最終ジャッジ日時 | 2025-06-12 16:35:50 |
合計ジャッジ時間 | 6,912 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 2 WA * 1 TLE * 1 -- * 13 |
ソースコード
import sys from itertools import permutations from collections import deque def main(): # Read input and setup initial and target positions initial_pos = {} target_pos = {} zero_initial = (3, 3) # Initial empty position (0-based) zero_target = None # Initialize initial positions (standard 15-puzzle) cnt = 1 for i in range(4): for j in range(4): if cnt <= 15: initial_pos[cnt] = (i, j) cnt += 1 # Read target configuration target = [] for i in range(4): row = list(map(int, sys.stdin.readline().split())) for j, num in enumerate(row): if num == 0: zero_target = (i, j) else: target_pos[num] = (i, j) target.extend(row) # Check standard solvability condition target_list = [num for num in target if num != 0] inv_count = 0 for i in range(len(target_list)): for j in range(i+1, len(target_list)): if target_list[i] > target_list[j]: inv_count += 1 row_initial = zero_initial[0] row_target = zero_target[0] row_diff = row_initial - row_target if (inv_count % 2) != (abs(row_diff) % 2): print("No") return # Check Manhattan distance for each tile possible = True for num in range(1, 16): if num not in initial_pos or num not in target_pos: continue ix, iy = initial_pos[num] tx, ty = target_pos[num] if abs(ix - tx) + abs(iy - ty) > 1: possible = False break if not possible: print("No") return # Collect pieces that need to be moved move_pieces = [] for num in range(1, 16): if initial_pos[num] != target_pos[num]: move_pieces.append(num) if not move_pieces: print("Yes") return # BFS function to check path from current empty to target position avoiding obstacles def bfs(start, goal, obstacles): visited = [[False]*4 for _ in range(4)] q = deque() q.append((start[0], start[1])) visited[start[0]][start[1]] = True dirs = [(-1,0), (1,0), (0,-1), (0,1)] while q: x, y = q.popleft() if (x, y) == goal: return True for dx, dy in dirs: nx, ny = x + dx, y + dy if 0 <= nx < 4 and 0 <= ny < 4: if not visited[nx][ny] and (nx, ny) not in obstacles: visited[nx][ny] = True q.append((nx, ny)) return False # Check each permutation of move_pieces for perm in permutations(move_pieces): current_empty = zero_initial moved = set() valid = True for piece in perm: init_x, init_y = initial_pos[piece] # Possible adjacent positions to the piece's initial position adjacent = [] for dx, dy in [(-1,0), (1,0), (0,-1), (0,1)]: nx, ny = init_x + dx, init_y + dy if 0 <= nx < 4 and 0 <= ny < 4: adjacent.append((nx, ny)) # Determine obstacles (unmoved pieces' initial positions) obstacles = set() for p in move_pieces: if p not in moved and p != piece: px, py = initial_pos[p] obstacles.add((px, py)) # Check if any adjacent position is reachable found = False for adj in adjacent: if bfs(current_empty, adj, obstacles): current_empty = (init_x, init_y) moved.add(piece) found = True break if not found: valid = False break if valid: print("Yes") return print("No") if __name__ == "__main__": main()