aacord’s memo

abcを中心にpythonで解いた問題のメモ、整理をしています。緑になった。

GCJ round 1B A (python)

Code Jam - Google’s Coding Competitions

Aしか解けず5点差で通過できず。C何とかして部分点取りたかった。インタラクティブはまだ入力の仕方がわからないので諦め。
Aは4方向に i 回目に 2**(i-1) 移動でき、(x,y) = (0,0) から、最終的に目的の座標に到達する最小手順を答える問題。
ゴールから逆算して (0,0) に到達する方法を考えた
i 回目以降ではどのように移動しても、移動距離が 2**(i-1) の倍数にしかならないことを考えれば、
i 回目 で (x,y) = (a,b) にいるとすると、
(a,b) == (0,0) or (a >> i & 1 ) ^ ( b >> i & 1 ) == 1 がIMPOSSIBLE とならないための必要条件となるとわかる。この前に abc の XOR sum 4 を解いていたのが大当たりした。だからこそ通過しておきたかったが…
D - Xor Sum 4

あとは (a,b) が (0,0) に到着する、もしくはIMPOSSIBLE になるまで4方向に bfs をしていけばよい
x方向かy方向かは c >> i & 1 == 1 となる方になる
bfs の実装が慣れてないので、座標と回数と文字列を全て持たせたままループさせた。
ゴールから逆算しているので、移動方向と反対方向の文字を持たせていることに注意。

n = int(input())
from collections import deque

def bfs(a,b,cnt,d):
    que = deque([])
    que.append((a, b, cnt, d))
    ans = 'IMPOSSIBLE'
    while que:
        p = que.popleft()
        if p[0] == 0 and p[1] == 0:
            ans = p[3]
            break
        if p[0]>>p[2]&1 == 1 and p[1]>>p[2]&1 != 1:
              que.append(((p[0]-2**p[2],p[1],p[2]+1,p[3]+'E'))) #E
              que.append(((p[0]+2**p[2],p[1],p[2]+1,p[3]+'W'))) #W
        if p[0]>>p[2]&1 != 1 and p[1]>>p[2]&1 == 1:
              que.append(((p[0],p[1]-2**p[2],p[2]+1,p[3]+'N'))) #N
              que.append(((p[0],p[1]+2**p[2],p[2]+1,p[3]+'S'))) #S
    return ans
  
    
for j in range(n):
    a, b = [int(i) for i in input().split()]
    ns = bfs(a,b,0,'')
    print('Case #{}: {}'.format(j+1,ns))