JMK no matter what

GCJ 2008 AMER Onsite 연습

실제로 돌지 않았던 온사이트가 몇 개 있어서 하나 돌아봤다. 2008년 아메리카 로컬 온사이트 셋인데.. 구현 A 와 퍼즐 B, 탐색 C 와 이지만 풀 수 있을 듯한 D 의 구성이었다. A 랑 C 는 금방 풀었는데 B 에서 디버그하느라 시간을 한참 소비. 2시간 10분 정도 걸려서 D1 까지 다 풀었는데.. 2시간 반인줄 알고 여유롭게 했는데 실제론 2시간이었다. -_-; 젠장.

B 에서의 패인은.. 답이 안나왔을때 헐 이거 왜이래 하고 그냥 대충 고쳐버린 것. 나중에 예제를 손으로 풀어보니.. 이것은 나의 실수. -_-; 바보다... ㅠㅠ 실제론 B 는 제끼고 D1 까지만 풀었어도 온사이트에 갈 수 있었다. B 를 좀 더 빨리 풀었으면 페널티로 3~4등일듯..

A: Mixing Bowls

구현.

lang:py
#!/usr/bin/python
import sys
from collections import defaultdict as ddict
f = sys.stdin
rl = lambda: f.readline().strip()

def go(mixture):
    bowls_needed = []
    for needed in recipe[mixture]:
        if needed.islower(): continue
        bowls_needed.append(go(needed))
    bowls = list(reversed(sorted(bowls_needed)))
    if len(bowls) == 0: return 1
    have = bowls[0]
    ret = have
    for b in bowls:
        if have < b:
            add = b - have
            have += add
            ret += add
        have -= 1
    if have == 0: ret += 1
    #print "%s => %d" % (mixture, ret)
    return ret

def solve(cc):
    global recipe, ingredients
    recipe = {}
    ingredients = set()
    n = int(rl())
    for i in range(n):
        line = rl().split()
        recipe[line[0]] = line[2:]
        for elem in line[2:]:
            ingredients.add(elem)
    for mixture in recipe.keys():
        if mixture not in ingredients:
            sol = go(mixture)

    print "Case #%d: %d" % (cc, sol)

def main(case):
    t = int(rl())
    for cc in range(1,t+1):
        if case == -1 or case == cc:
            solve(cc)

if __name__ == "__main__":
    args = sys.argv[1:]
    if len(args) >= 1: f = open(args[0])
    case = -1
    if len(args) >= 2: case = int(args[1])
    main(case)

B: Code Sequence

구현을 어떻게 할까 고민을 한참 했다. 결국 2^10 번만 돌아보면 된다는 것은 명확하다. 가장 쉬운 방법은 첫 번째 애의 하위 10비트가 무엇일까를 다 고민해보는 방법. 어느 경우에도 같은 답이 나오면 반환하고, 모호한 경우가 하나라도 있거나 다른 답이 나오면 unknown 을 찍으면 된다.

이 때, 마지막 숫자가 2진수로 1000 이고 그 다음에 출현할 것이 1001 차례면.. 4번째 비트에 해당하는 숫자가 뭔지 몰라도 다음 숫자를 찾을 수 있는데, 이걸 그냥 모호 처리했다가 예제가 안나왔다. 그래서 10비트를 적당히 n 에 비례해서 바꾸니 나오긴 나오는데.. 이게 바꾸는 게 말이 될 리가 없지 않은가? -_-; 결국 나중에 코드를 보면서 이거 맞나? 하고 예제 손으로 풀어보니 삽질이었다. 그거 하곤 가뿐히 둘다 패스.

lang:py
#!/usr/bin/python
import argparse, sys
from collections import defaultdict as ddict
f = sys.stdin
rl = lambda: f.readline().strip()

M = 10007

# None means doesn't make sense
# False means makes sense, but can't determine
def solve_for(seq, leftmost):
    c = []
    n = len(seq)
    for bit in range(100):
        value = False
        for i in range(len(seq)-1):
            me = leftmost + i
            next = leftmost + i + 1
            if (((me >> bit) & 1) == 0
                and (me >> bit) + 1 == (next >> bit)):
                me_value = seq[i]
                next_value = seq[i+1]
                for lower in range(bit):
                    if me & (1<<lower): me_value -= c[lower]
                    if next & (1<<lower): next_value -= c[lower]
                hypothesis = (next_value - me_value + M) % M
                if value == False:
                    value = hypothesis
                elif value != hypothesis:
                    return None
        if value == False:
            break
        c.append(value)
    next = leftmost + n
    last = next - 1
    sol = seq[-1]
    for i in range(100):
        if (next ^ last) & (1<<i):
            if i >= len(c):
                return False

    for i in range(len(c)):
        if ((next ^ last) & (1<<i)):
            if next & (1<<i):
                sol += c[i]
            else:
                sol -= c[i]
            sol = (sol + M) % M
    sol = (sol + M) % M
    return sol

def go(seq):
    sols = set()
    up = 1024
    for leftmost in range(up):
        cand = solve_for(seq, leftmost)
        if cand != None:
            sols.add(cand)
    if len(sols) != 1: return False
    return sols.pop()

def solve(cc):
    rl()
    seq = map(int, rl().split())
    ret = go(seq)
    print "Case #%d:" % cc,
    if ret == False:
        print "UNKNOWN"
    else:
        print ret

def main(case):
    t = int(rl())
    for cc in range(1,t+1):
        if case == -1 or case == cc:
            solve(cc)

if __name__ == "__main__":
    args = sys.argv[1:]
    if len(args) >= 1: f = open(args[0])
    case = -1
    if len(args) >= 2: case = int(args[1])
    main(case)

C: Test Passing Probability

각 답의 조합들이 서로 상관이 없다는 것을 스스로에게 설득시키고.. 그러면 그냥 제일 가능성 있는 것부터 해나가면 된다. 우선 순위 큐로 탐색.

lang:py
#!/usr/bin/python
from operator import mul
import argparse, sys, heapq
from collections import defaultdict as ddict
f = sys.stdin
rl = lambda: f.readline().strip()

def solve(cc):
    k, n = map(int, rl().split())
    probs = [map(float, rl().split()) for i in range(n)]
    for prob in probs: prob.sort(cmp=lambda a,b: cmp(b,a))
    ret = 0.0
    heap = []
    init = (-reduce(mul, [prob[0] for prob in probs]), [0] * n)
    seen = set()
    heapq.heappush(heap, init)
    for i in xrange(k):
        if len(heap) == 0: break
        prob, answers = heapq.heappop(heap)
        prob = -prob
        if prob == 0: break
        ret += prob
        #print prob, answers, ret
        for question in xrange(n):
            ans = answers[question]
            if ans < 3:
                nanswers = list(answers)
                nanswers[question] += 1
                if tuple(nanswers) in seen: continue
                seen.add(tuple(nanswers))
                np = prob * probs[question][ans+1] / probs[question][ans]
                heapq.heappush(heap, (-np, nanswers))
    print "Case #%d: %.12lf" % (cc, ret)

def main(case):
    t = int(rl())
    for cc in range(1,t+1):
        if case == -1 or case == cc:
            solve(cc)

if __name__ == "__main__":
    args = sys.argv[1:]
    if len(args) >= 1: f = open(args[0])
    case = -1
    if len(args) >= 2: case = int(args[1])
    main(case)

D: King

하드는 안드로. 이지는 캐쉽다.

lang:py
#!/usr/bin/python
import argparse, sys
from collections import defaultdict as ddict
f = sys.stdin
rl = lambda: f.readline().strip()

def wins(king, state):
    key = (king, state)
    if key in cache: return cache[key]
    ret = False
    y, x = king / w, king % w
    for ny in range(y-1,y+2):
        for nx in range(x-1,x+2):
            if 0 <= ny < h and 0 <= nx < w:
                if state & (2**idx[ny][nx]):
                    continue
                if not wins(idx[ny][nx], state + (2**idx[ny][nx])):
                    ret = True
                    break
        if ret: break
    cache[key] = ret
    return ret


def solve(cc):
    global h, w, board, idx, cache
    cache = {}
    h, w = map(int, rl().split())
    board = [rl() for i in range(h)]
    idx = [[i*w+j for j in range(w)] for i in range(h)]
    state = 0
    king = -1
    for i in range(h):
        for j in range(w):
            if board[i][j] != '.':
                state += (2**idx[i][j])
            if board[i][j] == 'K':
                king = idx[i][j]

    print "Case #%d: %s" % (cc, "A" if wins(king, state) else "B")


def main(case):
    t = int(rl())
    for cc in range(1,t+1):
        if case == -1 or case == cc:
            solve(cc)

if __name__ == "__main__":
    args = sys.argv[1:]
    if len(args) >= 1: f = open(args[0])
    case = -1
    if len(args) >= 2: case = int(args[1])
    main(case)
2010-06-10 14:03:49 | JM | /logs/ | 0 Comments

Leave a comment