Submission #57909913


Source Code Expand

#ZONe2021E Sneaking

#入力受取  R, Cは慣れないのでH, Wに変更
R, C = map(int, input().split())
H, W = R, C
A = [tuple(map(int, input().split())) for _ in range(H)]
B = [tuple(map(int, input().split())) for _ in range(H - 1)]

#頂点を倍加し、辺を張り直す
#(h, w, f): 現在値が(h, w)で、f = 1なら高速道路に移動した状態
convert = lambda h, w, f: (h * W + w) << 1 | f
G = [[] for _ in range(H * W * 2)]

#1. 左右の移動: コストA
for h in range(H):
    for w in range(W - 1):
        G[ convert(h, w, 0) ].append( (convert(h, w + 1, 0), A[h][w]) )
        G[ convert(h, w + 1, 0) ].append( (convert(h, w, 0), A[h][w]) )

#2. 上下の移動: コストB
for h in range(H - 1):
    for w in range(W):
        G[ convert(h, w, 0) ].append( (convert(h + 1, w, 0), B[h][w]) )

#3. 倍加した頂点間の移動: 倍加先に入るとコスト1
for h in range(H):
    for w in range(W):
        G[ convert(h, w, 0) ].append( (convert(h, w, 1), 1) )
        G[ convert(h, w, 1) ].append( (convert(h, w, 0), 0) )

#4. 倍加先の頂点の移動: 1マス降りるとコスト1
for h in range(H - 1):
    for w in range(W):
        G[ convert(h + 1, w, 1) ].append( (convert(h, w, 1), 1) )


#convert(0, 0, 0) から convert(H - 1, W - 1, 0) の最短路を求める問題に帰着できた
#ダイクストラだとおそらくTLEするのでDial algo.を用いる

#1. ダイクストラ法(SegTree)
def solve_SegTree():
    #dijkstra用SegTree  距離のchmin操作に対応
    class dijkstra_SegTree:  #ノードにvalueを直接代入する
        def __init__(self, N, inf):
            self._N, self._logN, self._size = N, N.bit_length(), 1 << N.bit_length()
            self._dist, self._node = [inf] * N, [inf] * (self._size << 1)
        def build(self, A):  #distをarray Aで初期化  O(N)
            assert len(A) == self._N
            for i, v in enumerate(A): self._dist[i] = self._node[i | self._size] = v
            for i in range(self._size - 1, 0, -1):
                self._node[i] = min(self._node[i << 1], self._node[i << 1 | 1])
        def chmin(self, i, v):  #dist[i] ← min(dist[i], v)  O(logN)
            if v < self._dist[i]:
                self._dist[i] = self._node[now := i | self._size] = v
                for _ in range(self._logN):
                    if v < self._node[now := now >> 1]: self._node[now] = v
                    else: return
        def get(self):  #【まだpopしていない】距離最小の頂点を取り出す  なければ-1  Θ(logN)
            if (v := self._node[now := 1]) == self._node[0]: return -1
            for _ in range(self._logN): now = e if self._node[e := now << 1] == v else e | 1
            m = self._node[i := now] = self._node[0]
            for _ in range(self._logN):
                if self._node[now ^ 1] < m: m = self._node[now ^ 1]
                self._node[now := now >> 1] = m
            return i ^ self._size
        def dist(self, i): return self._dist[i]

    ST = dijkstra_SegTree(H * W * 2, H * W * 10 ** 3)
    ST.chmin(convert(0, 0, 0), 0)  #初期化
    while True:
        i = ST.get()
        if i == -1: break
        for nxt, Ci in G[i]:
            ST.chmin(nxt, ST.dist(i) + Ci)
    return ST.dist( convert(H - 1, W - 1, 0) )


#2. ダイクストラ法(heapq)
def solve_heapq():
    import heapq
    DP = [H * W * 10 ** 3] * H * W * 2
    DP[0] = 0
    Q = [(0, 0)]
    while Q:
        dist, now = heapq.heappop(Q)
        if DP[now] < dist: continue
        DP[now] = dist
        for nxt, Ci in G[now]:
            if DP[nxt] > DP[now] + Ci:
                DP[nxt] = DP[now] + Ci
                heapq.heappush(Q, (DP[nxt], nxt))
    return DP[ convert(H - 1, W - 1, 0) ]


#2+. heapqを高速化  距離の最大値は2^31以下なのでtupleを回避できる
def solve_heapq_2():
    import heapq
    DP = [H * W * 10 ** 3] * H * W * 2
    DP[0] = 0
    mask = (1 << 31) - 1
    Q = [0 << 31 | 0]
    while Q:
        x = heapq.heappop(Q)
        dist, now = x >> 31, x & mask
        if DP[now] < dist: continue
        DP[now] = dist
        for nxt, Ci in G[now]:
            if DP[nxt] > DP[now] + Ci:
                DP[nxt] = DP[now] + Ci
                heapq.heappush(Q, DP[nxt] << 31 | nxt)
    return DP[ convert(H - 1, W - 1, 0) ]


#3. Dial algorithm
def solve_dial():
    #DP[i]: 頂点iの最短距離
    DP = [H * W * 10 ** 3] * H * W * 2
    DP[0] = 0
    Q = [[] for _ in range(1 << 10)]  #Dial algoのスタック
    Q[0].append(0)
    mask = (1 << 10) - 1  #除算用 ダイアル長が2冪ならand演算でよい
    for _ in range(- ( (- H * W * 10 ** 3) >> 10 )):  #最長距離を予測する
        for d in range(1 << 10):
            while Q[d]:
                i = Q[d].pop()
                if DP[i] & mask != d: continue
                for nxt, Ci in G[i]:
                    if DP[nxt] > DP[i] + Ci:
                        DP[nxt] = DP[i] + Ci
                        Q[ DP[nxt] & mask ].append(nxt)
    return DP[ convert(H - 1, W - 1, 0) ]



print(solve_dial())

Submission Info

Submission Time
Task E - Sneaking
User navel_tos
Language Python (PyPy 3.10-v7.3.12)
Score 500
Code Size 5198 Byte
Status AC
Exec Time 1969 ms
Memory 204436 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 500 / 500
Status
AC × 3
AC × 29
Set Name Test Cases
Sample 01_sample.txt, 02_sample.txt, 03_sample.txt
All 01_sample.txt, 02_sample.txt, 03_sample.txt, 04_random.txt, 05_random.txt, 06_random.txt, 07_random.txt, 08_random.txt, 09_random.txt, 10_random.txt, 11_random.txt, 12_random.txt, 13_random.txt, 14_random.txt, 15_random.txt, 16_random.txt, 17_random.txt, 18_random.txt, 19_random.txt, 20_random.txt, 21_random.txt, 22_random.txt, 23_random.txt, 24_max.txt, 25_max.txt, 26_max.txt, 27_max.txt, 28_zigzag.txt, 29_zigzag.txt
Case Name Status Exec Time Memory
01_sample.txt AC 59 ms 80432 KiB
02_sample.txt AC 61 ms 80460 KiB
03_sample.txt AC 59 ms 80284 KiB
04_random.txt AC 95 ms 83588 KiB
05_random.txt AC 231 ms 91992 KiB
06_random.txt AC 117 ms 84976 KiB
07_random.txt AC 63 ms 81292 KiB
08_random.txt AC 61 ms 80616 KiB
09_random.txt AC 99 ms 84336 KiB
10_random.txt AC 70 ms 81808 KiB
11_random.txt AC 213 ms 90488 KiB
12_random.txt AC 136 ms 86416 KiB
13_random.txt AC 904 ms 129064 KiB
14_random.txt AC 130 ms 85464 KiB
15_random.txt AC 123 ms 85516 KiB
16_random.txt AC 397 ms 101068 KiB
17_random.txt AC 86 ms 82532 KiB
18_random.txt AC 71 ms 81740 KiB
19_random.txt AC 140 ms 85816 KiB
20_random.txt AC 701 ms 118588 KiB
21_random.txt AC 65 ms 81608 KiB
22_random.txt AC 213 ms 90752 KiB
23_random.txt AC 70 ms 81696 KiB
24_max.txt AC 1883 ms 191440 KiB
25_max.txt AC 1969 ms 191616 KiB
26_max.txt AC 688 ms 204436 KiB
27_max.txt AC 1281 ms 191980 KiB
28_zigzag.txt AC 1821 ms 191376 KiB
29_zigzag.txt AC 1929 ms 191536 KiB