roiti46's blog

主に競プロ問題の解説を載せてます

yukicoder No.156 キャンディー・ボックス & No.157 2つの空洞

Cは解けなかったけどいい問題セットだった。問題はこちらから

No.156 キャンディーボックス

キャンディーがいくつか入った箱がN個ある。キャンディーの数が少ない箱から順番にキャンディーを食べていく。M個食べ終わった時に空になっている箱の数はいくつか。

解法

ある箱に入っているキャンディーが、まだ食べなければいけないキャンディーの数以下なら空となる。これを昇順にソートした箱に対して順番に試していけばいい。

N,M = map(int,raw_input().split())
C = sorted(map(int,raw_input().split()))
ans = 0
for i in xrange(N):
    if M >= C[i]:
        ans += 1
        M -= C[i]
print ans

No.157 2つの空洞

WxHの"#"(壁)と"."(空洞) からなる地図を与えられる。地図上には2つの空洞があり、壁をいくつか壊して1つの空洞にしてしまいたい。壊す必要のある壁の最小の数はいくつか。W,H ≦ 20。

解法

まず2つの空洞を区別するためにDFSで空洞をラベル化する(BFSでもOK)。そのあとに4重ループを回して、2つの地点が異なる空洞であるときにそのマンハッタン距離-1を計算し、最小値を取っていけばいい。O(W2 H2)だが制限が小さいので間に合う。他にもいろいろな解法がある教育的な問題ですね。

dxy = zip([1,0,-1,0],[0,1,0,-1])
def rec(x,y,cnt):
    C[y][x] = str(cnt)
    for dx,dy in dxy:
        nx,ny = x+dx,y+dy
        if 0 <= nx < W and 0 <= ny < H and C[ny][nx] == ".":
            rec(nx,ny,cnt)
            
W,H = map(int,raw_input().split())
C = [list(raw_input()) for i in xrange(H)]
cnt = 0
for y in xrange(H):
    for x in xrange(W):
        if C[y][x] == ".":
            rec(x,y,cnt)
            cnt += 1
ans = 100000
for y1 in xrange(H):
    for x1 in xrange(W):
        for y2 in xrange(H):
            for x2 in xrange(W):
                if C[y1][x1] == "0" and C[y2][x2] == "1":
                    ans = min(ans, abs(x1-x2)+abs(y1-y2))
print ans-1