Official

E - Hamiltonian Path Inversion Editorial by toam


\(A\) として以下のグリッドを出力します.

000000 ... 000000
001111 ... 111110
011111 ... 111110
000000 ... 000000

\(B\)\(1\) の個数(\(=2W-5\))とします.グリッドを内周(\(B\) 個の 1\(1\) 個の 0)と外周(\(2W+4\) 個の 0)に分けてそれぞれサイクルとみなします.

\(N=qB+r\ (0\leq r\lt B)\) とします.内側のサイクルを適切な箇所で切断して切り開く(0\(r+1\) 番目になるように)と,転倒数が \(r\) の列が作れます.切り開いた場所のすぐそばで外側のサイクルを切断し両者を接続して一つの大きなサイクルを作ります.この大きなサイクルを適切な場所で切り開く(\(2\) つのサイクルを接続させた部分から \(q\) 離れた場所)ことで転倒数を \(qB\) 増やすことができ,転倒数 \(N\) の 01 列が得られます.

この方法で \(0\leq N\leq 999975\) が達成可能です.

(実装例)

H, W, Q = map(int, input().split())
print("0" * W)
print("00" + "1" * (W - 3) + "0")
print("0" + "1" * (W - 2) + "0")
print("0" * W)

inner = [(1, i) for i in range(1, W - 1)] + [(2, i) for i in range(W - 2, 0, -1)]
outer = [(1, 0), (2, 0)] + [(3, i) for i in range(W)] + [(2, W - 1), (1, W - 1)] + [(0, i) for i in range(W - 1, -1, -1)]
B = 2 * W - 5


def dist(p, q):
    return abs(p[0] - q[0]) + abs(p[1] - q[1])


for _ in range(Q):
    N = int(input())
    q = N // B
    r = N % B
    ans_inner = inner[-r:] + inner[:-r]
    for i in range(len(outer)):
        if dist(ans_inner[0], outer[i - 1]) == dist(ans_inner[-1], outer[i]) == 1:
            ans_outer = outer[i:] + outer[:i]
            ans = ans_outer[q:] + ans_inner + ans_outer[:q]
            for x, y in ans:
                print(x + 1, y + 1)
            break

posted:
last update: