백준 13460 구슬 탈출2(Python)

박찬섭·2025년 4월 24일

알고리즘

목록 보기
16/16

코드

from collections import deque

R, C = map(int, input().split(" "))
dy = [0, 0, 1, -1]
dx = [1, -1, 0, 0]

board = []
r_y = 0
r_x = 0
b_y = 0
b_x = 0
for i in range(R):
    row = list(input())
    board.append(row)
    for j in range(len(row)):
        if row[j] == "R":
            r_y = i
            r_x = j
            board[i][j] = "."
        if row[j] == "B":
            b_y = i
            b_x = j
            board[i][j] = "."

queue = deque()
queue.append((r_y, r_x, b_y, b_x, 1))
visit = set([(r_y, r_x, b_y, b_x)])

def move(y, x, i):
    cnt = 0
    while board[y][x] != "O" and board[y][x] != "#":
        y += dy[i]
        x += dx[i]
        cnt += 1
    if board[y][x] == "O":
        return [y, x, cnt]
    if board[y][x] == "#":
        return [y - dy[i], x - dx[i], cnt]

find = False
while queue:
    cur_ry, cur_rx, cur_by, cur_bx, cur_k = queue.popleft()
    
    if cur_k > 10:
        continue
    
    if find:
        break
    
    for i in range(4):
        next_ry, next_rx, r_cnt = move(cur_ry, cur_rx, i)
        next_by, next_bx, b_cnt = move(cur_by, cur_bx, i)
        
        if board[next_ry][next_rx] == "O" and board[next_by][next_bx] == "O":
            continue
            
        if board[next_ry][next_rx] == "O" and board[next_by][next_bx] != "O":
            find = True
            print(cur_k)
            break
        
        if next_ry == next_by and next_rx == next_bx:
            if r_cnt < b_cnt:
                next_by -= dy[i]
                next_bx -= dx[i]
            if r_cnt > b_cnt:
                next_ry -= dy[i]
                next_rx -= dx[i]
        
        if (next_ry, next_rx, next_by, next_bx) not in visit:
            queue.append((next_ry, next_rx, next_by, next_bx, cur_k + 1))
            visit.add((next_ry, next_rx, next_by, next_bx))
              
if not find:
    print(-1)

구슬 탈출 문제로 주요 로직은 구슬 겹침 문제인 것 같다.

처음에는 구슬을 따로따로 한 칸씩 움직여 로직을 구성했었다.

from collections import deque

R, C = map(int, input().split(" "))
dy = [0, 0, 1, -1]
dx = [1, -1, 0, 0]

board = []
r_y = 0
r_x = 0
b_y = 0
b_x = 0
for i in range(R):
    row = list(input())
    board.append(row)
    for j in range(len(row)):
        if row[j] == "R":
            r_y = i
            r_x = j
            board[i][j] = "."
        if row[j] == "B":
            b_y = i
            b_x = j
            board[i][j] = "."

queue = deque()
queue.append((r_y, r_x, b_y, b_x, 1))
visit = set([(r_y, r_x, b_y, b_x)])
find = False
while queue:
    cur_ry, cur_rx, cur_by, cur_bx, cur_k = queue.popleft()
    
    if find:
        break
    
    # print(f"ry : {cur_ry}, rx : {cur_rx} | by : {cur_by}, bx : {cur_bx}")
    if cur_k > 10:
        continue
    
    for i in range(4):
        if find:
            break
        r_stop = False
        b_stop = False
        next_ry = cur_ry
        next_rx = cur_rx
        next_by = cur_by
        next_bx = cur_bx
        
        r_in_hole = False
        b_in_hole = False
        
        while (not r_stop or not b_stop):
            nnry = next_ry + dy[i]
            nnrx = next_rx + dx[i]
            # print(f"ry : {next_ry}, rx : {next_rx} | by : {next_by}, bx : {next_bx}")
            if (not r_stop and (0 <= nnry < R and 0 <= nnrx < C)) and (nnry != next_by or nnrx != next_bx):
                next_ry += dy[i]
                next_rx += dx[i]
            
            nnby = next_by + dy[i]
            nnbx = next_bx + dx[i]
            if (not b_stop and (0 <= nnby < R and 0 <= nnbx < C)) and (nnby != next_ry or nnbx != next_rx):
                next_by += dy[i]
                next_bx += dx[i]    
            
            if board[next_ry][next_rx] == "#":
                r_stop = True
                board[next_ry - dy[i]][next_rx - dx[i]] = "#"
            if board[next_by][next_bx] == "#":
                b_stop = True
                board[next_by - dy[i]][next_bx - dx[i]] = "#"            

            if board[next_ry][next_rx] == "O":
                r_in_hole = True                
            
            if board[next_by][next_bx] == "O":
                b_in_hole = True
        
        next_ry -= dy[i]
        next_rx -= dx[i]
        next_by -= dy[i]
        next_bx -= dx[i]
        board[next_ry][next_rx] = "."
        board[next_by][next_bx] = "."
        if not (next_ry, next_rx, next_by, next_bx) in visit:
            queue.append((next_ry, next_rx, next_by, next_bx, cur_k + 1))
            visit.add((next_ry, next_rx, next_by, next_bx))
            # print(f"result : ry : {next_ry}, rx : {next_rx} | by : {next_by}, bx : {next_bx}\n")
        
        if r_in_hole and not b_in_hole:
            find = True
            print(cur_k)
            break
        
if not find:
    print(-1)

겹침 문제는 동시에 공을 굴리고 움직인 수가 더 많은 공을 한 칸 뒤로 미는것으로 수정했다.

profile
백엔드 개발자를 희망하는

0개의 댓글