[BOJ/Python]20304パスワード作成



この問題は幅優先探索とビットマスクを組み合わせた方法で解いた.一人の力が近づきにくいので、グーグルの力で解決しました.この問題の核心は,(시도한 비밀번호) XOR (1이 k개 들어간 임의의 bit) = 비밀번호 후보で得られた비밀번호 후보を用いて(비밀번호 후보) XOR (시도한 비밀번호) = 1이 k개 들어간 임의의 bitを再求め,このとき任意のビットの1個数が安全距離となることである.
従って、現在の安全距離と安全距離とが1だけ異なるパスワード候補の安全距離を更新することにより解決される.幅優先検索なので、パスワード候補のセキュリティ距離を更新する場合は、その候補を検索するためにキューにパスワード候補を追加する必要があります.
  • nと入力します.
  • mと入力します.
  • を試したパスワードリストハッカーを入力します.
  • の最大長を示す変数mx lenには、nがバイナリ数に変換されたときの長さが格納される.
  • 安全距離リスト安全用mx len+1 n+1個充填.
  • 幅優先探索で使用されるキューdqはdequeである.
  • ハッカーを巡るiにリクエスト.
    ->safety[i]が0に更新されました.
    ->dqにiを加える.
  • の正解を保存する変数の答えを0にします.
  • dqが存在する間、ドアを繰り返し回転させる.
    ->dq抽出cur.
    ->mx lenのiのfor文.
    -->(1이 i개 들어간 임의의 bit) XOR (현재 비밀번호 후보)の値を一時変数xに格納します.
    -->xがn以下の場合、safety[cur]+1safety[x]未満である.
    -->safety[x]safety[cur]+1に更新されました.
    ----->答えをsafety[x]と答えのより大きな値に更新します.
    -->dqプラスx.
  • の回答を印刷します.
  • Code

    import collections
    import sys
    input=sys.stdin.readline
    n=int(input())
    m=int(input())
    hacker=list(map(int, input().split()))
    mx_len=len(bin(n)[2:])
    safety=[mx_len+1 for _ in range(n+1)]
    dq=collections.deque()
    for i in hacker:
        safety[i]=0
        dq.append(i)
    answer=0
    while dq:
        cur=dq.popleft()
        for i in range(mx_len):
           x=(1<<i)^cur
           if x<=n and safety[cur]+1<safety[x]:
               safety[x]=safety[cur]+1
               answer=max(safety[x], answer)
               dq.append(x)
    print(answer)