提出 #76871380
ソースコード 拡げる
import sys
from collections import deque
import time
def solve():
input = sys.stdin.readline
N, M, K = map(int, input().split())
grid = [input().strip() for _ in range(N)]
door_h = [[-1] * N for _ in range(N - 1)]
door_v = [[-1] * (N - 1) for _ in range(N)]
switch = [[-1] * N for _ in range(N)]
switch_pos = [None] * K
used_switch = [False] * K
doors_placed = 0
def is_open(g, mask):
if g == -1:
return True
k = g // 2
return ((mask >> k) & 1) == (g & 1)
# 完全BFS(Tを返す)
def calc_T():
INF = -1
total = N * N
size = (1 << K) * total
dist = [INF] * size
dist[0] = 0
q = deque([0])
while q:
idx = q.popleft()
d = dist[idx]
mask = idx // total
pos = idx % total
i = pos // N
j = pos % N
if i == N - 1 and j == N - 1:
return d
for di, dj in ((-1,0),(1,0),(0,-1),(0,1)):
ni, nj = i + di, j + dj
if not (0 <= ni < N and 0 <= nj < N):
continue
if grid[ni][nj] == '#':
continue
if di == 1:
g = door_h[i][j]
elif di == -1:
g = door_h[ni][nj]
elif dj == 1:
g = door_v[i][j]
else:
g = door_v[ni][nj]
if not is_open(g, mask):
continue
nidx = mask * total + ni * N + nj
if dist[nidx] == INF:
dist[nidx] = d + 1
q.append(nidx)
s = switch[i][j]
if s != -1:
nmask = mask ^ (1 << s)
nidx = nmask * total + i * N + j
if dist[nidx] == INF:
dist[nidx] = d + 1
q.append(nidx)
return 0
# 経路復元つきBFS
def calc_T_with_path():
INF = -1
total = N * N
size = (1 << K) * total
dist = [INF] * size
prev = [(-1, -1, -1)] * size
dist[0] = 0
q = deque([0])
while q:
idx = q.popleft()
d = dist[idx]
mask = idx // total
pos = idx % total
i = pos // N
j = pos % N
if i == N - 1 and j == N - 1:
path = []
cur = idx
while cur != -1:
cm = cur // total
cp = cur % total
ci = cp // N
cj = cp % N
path.append((cm, ci, cj))
p = prev[cur]
if p[0] == -1:
break
cur = p[0] * total + p[1] * N + p[2]
path.reverse()
return d, path
for di, dj in ((-1,0),(1,0),(0,-1),(0,1)):
ni, nj = i + di, j + dj
if not (0 <= ni < N and 0 <= nj < N):
continue
if grid[ni][nj] == '#':
continue
if di == 1:
g = door_h[i][j]
elif di == -1:
g = door_h[ni][nj]
elif dj == 1:
g = door_v[i][j]
else:
g = door_v[ni][nj]
if not is_open(g, mask):
continue
nidx = mask * total + ni * N + nj
if dist[nidx] == INF:
dist[nidx] = d + 1
prev[nidx] = (mask, i, j)
q.append(nidx)
s = switch[i][j]
if s != -1:
nmask = mask ^ (1 << s)
nidx = nmask * total + i * N + j
if dist[nidx] == INF:
dist[nidx] = d + 1
prev[nidx] = (mask, i, j)
q.append(nidx)
return 0, []
# 固定マスクの到達可能範囲(スイッチ操作なし)
def bfs_reachable(start_mask, start_i, start_j, blocked_edge=None):
dist = [[-1] * N for _ in range(N)]
dist[start_i][start_j] = 0
q = deque([(start_i, start_j)])
while q:
i, j = q.popleft()
d = dist[i][j]
for di, dj in ((-1,0),(1,0),(0,-1),(0,1)):
ni, nj = i + di, j + dj
if not (0 <= ni < N and 0 <= nj < N):
continue
if grid[ni][nj] == '#':
continue
if blocked_edge:
bi1, bj1, bi2, bj2 = blocked_edge
if (i==bi1 and j==bj1 and ni==bi2 and nj==bj2) or (i==bi2 and j==bj2 and ni==bi1 and nj==bj1):
continue
if di == 1:
g = door_h[i][j]
elif di == -1:
g = door_h[ni][nj]
elif dj == 1:
g = door_v[i][j]
else:
g = door_v[ni][nj]
if not is_open(g, start_mask):
continue
if dist[ni][nj] == -1:
dist[ni][nj] = d + 1
q.append((ni, nj))
return dist
start_time = time.time()
TIME_LIMIT = 1.8 # 安全マージン
# ----- メイン貪欲 -----
current_T, current_path = calc_T_with_path()
for k in range(K):
if time.time() - start_time > TIME_LIMIT:
break
improved = True
while improved and doors_placed < M:
if time.time() - start_time > TIME_LIMIT:
break
if not current_path:
break
# 経路上の辺を列挙(最大50本)
edges = []
prev = current_path[0]
for state in current_path[1:]:
if state[1] != prev[1] or state[2] != prev[2]:
if state[1] == prev[1]: # 横移動
jj = min(state[2], prev[2])
edges.append(('h', prev[1], jj, prev[0], prev[1], prev[2]))
else: # 縦移動
ii = min(state[1], prev[1])
edges.append(('v', ii, prev[2], prev[0], prev[1], prev[2]))
prev = state
best_gain = 0
best_door = None
best_sw_pos = None
seen = set()
for edge in edges[:50]: # 最初の50本だけ試す
typ, ei, ej, emask, fi, fj = edge
if typ == 'v':
if door_h[ei][ej] != -1:
continue
key = ('v', ei, ej)
blocked = (ei, ej, ei+1, ej)
else:
if door_v[ei][ej] != -1:
continue
key = ('h', ei, ej)
blocked = (ei, ej, ei, ej+1)
if key in seen:
continue
seen.add(key)
# スイッチ位置候補(最遠の空きマス)
reach = bfs_reachable(emask, fi, fj, blocked)
cand_sw = None
max_d = -1
for si in range(N):
for sj in range(N):
if reach[si][sj] != -1 and switch[si][sj] == -1 and grid[si][sj] == '.':
d = reach[si][sj]
if d > max_d:
max_d = d
cand_sw = (si, sj)
if cand_sw is None:
continue
# 仮設置
if typ == 'v':
door_h[ei][ej] = 2 * k + 1
else:
door_v[ei][ej] = 2 * k + 1
si, sj = cand_sw
old_sw_val = switch[si][sj]
switch[si][sj] = k
if not used_switch[k]:
# 未使用ならスイッチ位置を仮更新
old_sw_pos = switch_pos[k]
old_used = used_switch[k]
new_T = calc_T()
gain = new_T - current_T
# 元に戻す
if typ == 'v':
door_h[ei][ej] = -1
else:
door_v[ei][ej] = -1
if old_sw_val != -1:
switch[si][sj] = old_sw_val
else:
switch[si][sj] = -1
if not used_switch[k]:
switch_pos[k] = old_sw_pos
used_switch[k] = old_used
if gain > best_gain:
best_gain = gain
best_door = (typ, ei, ej)
best_sw_pos = cand_sw
if best_gain > 0 and best_door is not None:
# 設置確定
typ, ei, ej = best_door
if typ == 'v':
door_h[ei][ej] = 2 * k + 1
else:
door_v[ei][ej] = 2 * k + 1
si, sj = best_sw_pos
if not used_switch[k]:
switch[si][sj] = k
switch_pos[k] = (si, sj)
used_switch[k] = True
else:
# 既存のスイッチをより遠くへ移動
old_si, old_sj = switch_pos[k]
switch[old_si][old_sj] = -1
switch[si][sj] = k
switch_pos[k] = (si, sj)
doors_placed += 1
current_T, current_path = calc_T_with_path()
improved = True
else:
# このスイッチ種類では改善不可
if not used_switch[k]:
# スイッチだけでも設置(入口から最遠)
best_sw = None
max_d = -1
for si in range(N):
for sj in range(N):
if grid[si][sj] == '.' and switch[si][sj] == -1:
d = bfs_reachable(0,0,0)[si][sj]
if d > max_d and d != -1:
max_d = d
best_sw = (si, sj)
if best_sw:
si, sj = best_sw
switch[si][sj] = k
switch_pos[k] = (si, sj)
used_switch[k] = True
break
# ----- 出力 -----
doors = []
for i in range(N-1):
for j in range(N):
if door_h[i][j] != -1:
doors.append((0, i, j, door_h[i][j]))
for i in range(N):
for j in range(N-1):
if door_v[i][j] != -1:
doors.append((1, i, j, door_v[i][j]))
print(len(doors))
for d, i, j, g in doors:
print(d, i, j, g)
switches_out = []
for i in range(N):
for j in range(N):
if switch[i][j] != -1:
switches_out.append((i, j, switch[i][j]))
print(len(switches_out))
for i, j, s in switches_out:
print(i, j, s)
if __name__ == "__main__":
solve()
提出情報
| 提出日時 | |
|---|---|
| 問題 | A - Castle Renovation with Linked Doors |
| ユーザ | Takkun2355 |
| 言語 | Python (PyPy 3.11-v7.3.20) |
| 得点 | 384348947 |
| コード長 | 11678 Byte |
| 結果 | AC |
| 実行時間 | 1988 ms |
| メモリ | 546300 KiB |
ジャッジ結果
| セット名 | test_ALL | ||
|---|---|---|---|
| 得点 / 配点 | 384348947 / 3000000000 | ||
| 結果 |
|
| セット名 | テストケース |
|---|---|
| test_ALL | test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt |
| ケース名 | 結果 | 実行時間 | メモリ |
|---|---|---|---|
| test_0000.txt | AC | 1061 ms | 518388 KiB |
| test_0001.txt | AC | 952 ms | 539892 KiB |
| test_0002.txt | AC | 1120 ms | 542264 KiB |
| test_0003.txt | AC | 1194 ms | 539688 KiB |
| test_0004.txt | AC | 1037 ms | 540804 KiB |
| test_0005.txt | AC | 1267 ms | 502080 KiB |
| test_0006.txt | AC | 1552 ms | 543028 KiB |
| test_0007.txt | AC | 1255 ms | 545464 KiB |
| test_0008.txt | AC | 1217 ms | 542964 KiB |
| test_0009.txt | AC | 829 ms | 510528 KiB |
| test_0010.txt | AC | 935 ms | 536448 KiB |
| test_0011.txt | AC | 1527 ms | 400156 KiB |
| test_0012.txt | AC | 1912 ms | 454288 KiB |
| test_0013.txt | AC | 1024 ms | 542276 KiB |
| test_0014.txt | AC | 1354 ms | 539704 KiB |
| test_0015.txt | AC | 1287 ms | 488260 KiB |
| test_0016.txt | AC | 1514 ms | 542732 KiB |
| test_0017.txt | AC | 990 ms | 540372 KiB |
| test_0018.txt | AC | 911 ms | 539184 KiB |
| test_0019.txt | AC | 940 ms | 536884 KiB |
| test_0020.txt | AC | 1290 ms | 542832 KiB |
| test_0021.txt | AC | 1219 ms | 539660 KiB |
| test_0022.txt | AC | 1316 ms | 539680 KiB |
| test_0023.txt | AC | 1302 ms | 542832 KiB |
| test_0024.txt | AC | 1546 ms | 501544 KiB |
| test_0025.txt | AC | 1627 ms | 459984 KiB |
| test_0026.txt | AC | 1100 ms | 539152 KiB |
| test_0027.txt | AC | 910 ms | 540140 KiB |
| test_0028.txt | AC | 1666 ms | 539548 KiB |
| test_0029.txt | AC | 976 ms | 545524 KiB |
| test_0030.txt | AC | 1594 ms | 482152 KiB |
| test_0031.txt | AC | 1209 ms | 539596 KiB |
| test_0032.txt | AC | 903 ms | 539676 KiB |
| test_0033.txt | AC | 1186 ms | 540864 KiB |
| test_0034.txt | AC | 1073 ms | 542360 KiB |
| test_0035.txt | AC | 1475 ms | 539788 KiB |
| test_0036.txt | AC | 1161 ms | 539600 KiB |
| test_0037.txt | AC | 1088 ms | 539948 KiB |
| test_0038.txt | AC | 866 ms | 539740 KiB |
| test_0039.txt | AC | 1311 ms | 539696 KiB |
| test_0040.txt | AC | 1150 ms | 539336 KiB |
| test_0041.txt | AC | 1152 ms | 538936 KiB |
| test_0042.txt | AC | 1027 ms | 459452 KiB |
| test_0043.txt | AC | 1325 ms | 542884 KiB |
| test_0044.txt | AC | 1200 ms | 539004 KiB |
| test_0045.txt | AC | 987 ms | 536688 KiB |
| test_0046.txt | AC | 989 ms | 542944 KiB |
| test_0047.txt | AC | 1473 ms | 539828 KiB |
| test_0048.txt | AC | 761 ms | 539120 KiB |
| test_0049.txt | AC | 1270 ms | 539672 KiB |
| test_0050.txt | AC | 957 ms | 542908 KiB |
| test_0051.txt | AC | 1169 ms | 542284 KiB |
| test_0052.txt | AC | 863 ms | 541004 KiB |
| test_0053.txt | AC | 1336 ms | 542904 KiB |
| test_0054.txt | AC | 1008 ms | 546300 KiB |
| test_0055.txt | AC | 991 ms | 539740 KiB |
| test_0056.txt | AC | 1350 ms | 545424 KiB |
| test_0057.txt | AC | 1294 ms | 542364 KiB |
| test_0058.txt | AC | 1337 ms | 539040 KiB |
| test_0059.txt | AC | 1273 ms | 539840 KiB |
| test_0060.txt | AC | 980 ms | 539928 KiB |
| test_0061.txt | AC | 1354 ms | 542972 KiB |
| test_0062.txt | AC | 1396 ms | 539732 KiB |
| test_0063.txt | AC | 1207 ms | 504824 KiB |
| test_0064.txt | AC | 1079 ms | 539592 KiB |
| test_0065.txt | AC | 1644 ms | 539780 KiB |
| test_0066.txt | AC | 1000 ms | 539472 KiB |
| test_0067.txt | AC | 1011 ms | 543268 KiB |
| test_0068.txt | AC | 884 ms | 517624 KiB |
| test_0069.txt | AC | 1383 ms | 537280 KiB |
| test_0070.txt | AC | 1103 ms | 539028 KiB |
| test_0071.txt | AC | 1669 ms | 542284 KiB |
| test_0072.txt | AC | 1014 ms | 539632 KiB |
| test_0073.txt | AC | 1348 ms | 541064 KiB |
| test_0074.txt | AC | 940 ms | 539096 KiB |
| test_0075.txt | AC | 933 ms | 466892 KiB |
| test_0076.txt | AC | 1071 ms | 539628 KiB |
| test_0077.txt | AC | 946 ms | 542536 KiB |
| test_0078.txt | AC | 998 ms | 520936 KiB |
| test_0079.txt | AC | 1313 ms | 539916 KiB |
| test_0080.txt | AC | 1197 ms | 542588 KiB |
| test_0081.txt | AC | 889 ms | 540368 KiB |
| test_0082.txt | AC | 884 ms | 542460 KiB |
| test_0083.txt | AC | 1070 ms | 542456 KiB |
| test_0084.txt | AC | 1337 ms | 539700 KiB |
| test_0085.txt | AC | 1346 ms | 539864 KiB |
| test_0086.txt | AC | 1424 ms | 539828 KiB |
| test_0087.txt | AC | 1324 ms | 495836 KiB |
| test_0088.txt | AC | 1099 ms | 514584 KiB |
| test_0089.txt | AC | 1103 ms | 539800 KiB |
| test_0090.txt | AC | 1231 ms | 539372 KiB |
| test_0091.txt | AC | 1182 ms | 539952 KiB |
| test_0092.txt | AC | 1153 ms | 540544 KiB |
| test_0093.txt | AC | 966 ms | 542932 KiB |
| test_0094.txt | AC | 821 ms | 539060 KiB |
| test_0095.txt | AC | 1290 ms | 436952 KiB |
| test_0096.txt | AC | 1143 ms | 545668 KiB |
| test_0097.txt | AC | 1111 ms | 539816 KiB |
| test_0098.txt | AC | 952 ms | 539596 KiB |
| test_0099.txt | AC | 1443 ms | 540168 KiB |
| test_0100.txt | AC | 927 ms | 539228 KiB |
| test_0101.txt | AC | 831 ms | 540716 KiB |
| test_0102.txt | AC | 1235 ms | 540504 KiB |
| test_0103.txt | AC | 1475 ms | 517096 KiB |
| test_0104.txt | AC | 1351 ms | 540292 KiB |
| test_0105.txt | AC | 1036 ms | 539180 KiB |
| test_0106.txt | AC | 902 ms | 540664 KiB |
| test_0107.txt | AC | 1473 ms | 540180 KiB |
| test_0108.txt | AC | 852 ms | 539608 KiB |
| test_0109.txt | AC | 1121 ms | 540796 KiB |
| test_0110.txt | AC | 1681 ms | 539920 KiB |
| test_0111.txt | AC | 1278 ms | 542936 KiB |
| test_0112.txt | AC | 1092 ms | 539584 KiB |
| test_0113.txt | AC | 1072 ms | 492092 KiB |
| test_0114.txt | AC | 856 ms | 543024 KiB |
| test_0115.txt | AC | 959 ms | 539468 KiB |
| test_0116.txt | AC | 1367 ms | 540088 KiB |
| test_0117.txt | AC | 1139 ms | 529804 KiB |
| test_0118.txt | AC | 1988 ms | 421168 KiB |
| test_0119.txt | AC | 1222 ms | 542480 KiB |
| test_0120.txt | AC | 1151 ms | 542848 KiB |
| test_0121.txt | AC | 1089 ms | 542872 KiB |
| test_0122.txt | AC | 1261 ms | 539676 KiB |
| test_0123.txt | AC | 1479 ms | 539776 KiB |
| test_0124.txt | AC | 1238 ms | 542152 KiB |
| test_0125.txt | AC | 1250 ms | 542304 KiB |
| test_0126.txt | AC | 1177 ms | 539760 KiB |
| test_0127.txt | AC | 1500 ms | 520608 KiB |
| test_0128.txt | AC | 1251 ms | 523328 KiB |
| test_0129.txt | AC | 1771 ms | 542772 KiB |
| test_0130.txt | AC | 960 ms | 539680 KiB |
| test_0131.txt | AC | 1384 ms | 542964 KiB |
| test_0132.txt | AC | 1733 ms | 539652 KiB |
| test_0133.txt | AC | 1061 ms | 540080 KiB |
| test_0134.txt | AC | 1149 ms | 539684 KiB |
| test_0135.txt | AC | 1529 ms | 443416 KiB |
| test_0136.txt | AC | 1082 ms | 542316 KiB |
| test_0137.txt | AC | 1021 ms | 536892 KiB |
| test_0138.txt | AC | 1132 ms | 540480 KiB |
| test_0139.txt | AC | 1450 ms | 536612 KiB |
| test_0140.txt | AC | 1028 ms | 539776 KiB |
| test_0141.txt | AC | 1366 ms | 537848 KiB |
| test_0142.txt | AC | 890 ms | 546104 KiB |
| test_0143.txt | AC | 1248 ms | 542212 KiB |
| test_0144.txt | AC | 1051 ms | 531044 KiB |
| test_0145.txt | AC | 1275 ms | 539540 KiB |
| test_0146.txt | AC | 967 ms | 540548 KiB |
| test_0147.txt | AC | 1417 ms | 539688 KiB |
| test_0148.txt | AC | 1117 ms | 537308 KiB |
| test_0149.txt | AC | 1266 ms | 539964 KiB |