結果
| 問題 |
No.3121 Prime Dance
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-04-20 05:07:05 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 6,078 bytes |
| コンパイル時間 | 335 ms |
| コンパイル使用メモリ | 13,312 KB |
| 実行使用メモリ | 13,568 KB |
| 最終ジャッジ日時 | 2025-04-20 05:07:09 |
| 合計ジャッジ時間 | 3,093 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 17 WA * 4 |
ソースコード
from heapq import heappush, heappop
from collections import deque
def solve():
H,W = map(int,input().split())
sx,sy = map(lambda x:int(x)-1, input().split())
gx,gy = map(lambda x:int(x)-1, input().split())
A = [list(input().rstrip()) for _ in range(H)]
dx = gx - sx
dy = gy - sy
vis = [[False]*W for _ in range(H)]
dq = deque([(sx,sy)])
vis[sx][sy] = True
while dq:
x,y = dq.popleft()
for dxx,dyy in ((1,0),(-1,0),(0,1),(0,-1)):
nx,ny = x+dxx, y+dyy
if 0<=nx<H and 0<=ny<W and not vis[nx][ny] and A[nx][ny] != '#':
vis[nx][ny] = True
dq.append((nx,ny))
if not vis[gx][gy]:
print(-1)
return
pareto = [[[] for _ in range(W)] for __ in range(H)]
pq = [(0,0,0,sx,sy)]
pareto[sx][sy].append((0,0))
while pq:
_, v, h, x, y = heappop(pq)
dominated = False
for vv,hh in pareto[x][y]:
if vv<=v and hh<=h and (vv,hh)!=(v,h):
dominated = True; break
if dominated: continue
for dxx,dyy in ((1,0),(-1,0),(0,1),(0,-1)):
nx,ny = x+dxx, y+dyy
if not (0<=nx<H and 0<=ny<W and A[nx][ny] != '#'): continue
nv, nh = v + (1 if dxx!=0 else 0), h + (1 if dyy!=0 else 0)
skip = False
remove = []
for idx,(vv,hh) in enumerate(pareto[nx][ny]):
if vv<=nv and hh<=nh:
skip = True; break
if nv<=vv and nh<=hh:
remove.append(idx)
if skip: continue
for idx in reversed(remove):
pareto[nx][ny].pop(idx)
pareto[nx][ny].append((nv,nh))
heappush(pq, (nv+nh, nv, nh, nx, ny))
MAXP = 200000
is_prime = [True]*(MAXP+1)
is_prime[0]=is_prime[1]=False
for i in range(2,MAXP+1):
if is_prime[i]:
for j in range(i+i, MAXP+1, i):
is_prime[j] = False
def min_pad(big, small):
for t in range(0, MAXP-big+1):
if big == 0 and t != 0:
break
p = big + t
q = small + t
if q<2: continue
if is_prime[p] and is_prime[q]:
return t
return None
ans = None
for V_,H_ in pareto[gx][gy]:
A0 = (V_ + dx)//2
B0 = (V_ - dx)//2
C0 = (H_ + dy)//2
D0 = (H_ - dy)//2
pad_v = min_pad(max(A0,B0), min(A0,B0))
pad_h = min_pad(max(C0,D0), min(C0,D0))
if pad_v is None or pad_h is None:
continue
total = (V_+H_) + 2*pad_v + 2*pad_h
if ans is None or total<ans:
ans = total
dist0 = [[-1]*W for _ in range(H)]
parent = [[None]*W for _ in range(H)]
dq2 = deque([(sx,sy)])
dist0[sx][sy] = 0
while dq2:
x,y = dq2.popleft()
for dx_,dy_,op in ((1,0,'A'),(-1,0,'B'),(0,1,'C'),(0,-1,'D')):
nx,ny = x+dx_, y+dy_
if 0<=nx<H and 0<=ny<W and A[nx][ny] != '#' and dist0[nx][ny] < 0:
dist0[nx][ny] = dist0[x][y] + 1
parent[nx][ny] = (x,y,op)
dq2.append((nx,ny))
A1=B1=C1=D1 = 0
path = []
cx,cy = gx,gy
while (cx,cy) != (sx,sy):
path.append((cx,cy))
px,py,op = parent[cx][cy]
if op=='A': A1 += 1
elif op=='B': B1 += 1
elif op=='C': C1 += 1
else: D1 += 1
cx,cy = px,py
path.append((sx,sy))
if not ( (A1+B1>0) and (C1+D1>0) ):
d2 = [[-1]*W for _ in range(H)]
dq3 = deque(path)
for x,y in path:
d2[x][y] = 0
while dq3:
x,y = dq3.popleft()
for dx_,dy_ in ((1,0),(-1,0),(0,1),(0,-1)):
nx,ny = x+dx_, y+dy_
if 0<=nx<H and 0<=ny<W and A[nx][ny] != '#' and d2[nx][ny]<0:
d2[nx][ny] = d2[x][y] + 1
dq3.append((nx,ny))
# 5) 縦移動ペア&横移動ペアまでの最小距離を探す
INF = 10**9
best_v = INF
for i in range(H-1):
for j in range(W):
if A[i][j] != '#' and A[i+1][j] != '#':
# path→(i,j) or (i+1,j) の距離
for (ii,jj) in ((i,j),(i+1,j)):
if d2[ii][jj]>=0:
best_v = min(best_v, d2[ii][jj])
best_h = INF
for i in range(H):
for j in range(W-1):
if A[i][j] != '#' and A[i][j+1] != '#':
for (ii,jj) in ((i,j),(i,j+1)):
if d2[ii][jj]>=0:
best_h = min(best_h, d2[ii][jj])
base0 = A1 + B1 + C1 + D1 # 最短路長
extra = 0
# 縦移動ゼロならループ寄り道
if A1+B1 == 0:
if best_v < INF:
extra += 2*best_v + 4
else:
extra = INF
# 横移動ゼロならループ寄り道
if C1+D1 == 0:
if best_h < INF:
extra += 2*best_h + 4
else:
extra = INF
# ── ここから素数パディング追加 ──
if extra < INF:
# 縦移動のパディング
if A1+B1 == 0:
# 2往復して A'=B'=2 なので、2は素数→パディング不要
pad_v_exc = 0
else:
pad_v_exc = min_pad(max(A1,B1), min(A1,B1))
# 横移動のパディング
if C1+D1 == 0:
pad_h_exc = 0
else:
pad_h_exc = min_pad(max(C1,D1), min(C1,D1))
# 両方 None でないことを確認してマージ
if pad_v_exc is not None and pad_h_exc is not None:
cand = base0 + extra + 2*pad_v_exc + 2*pad_h_exc
ans = cand if ans is None else min(ans, cand)
# ── ここまで素数パディング追加 ──
print(ans if ans is not None else -1)
solve()
"""
2 3
2 2
2 3
.##
.SG
"""