SW 역량 문제집 풀이

이미리·2023년 12월 31일
0

boj_Algorithm

목록 보기
24/25

2024년 새해를 맞아.. 새로운 문제집을 풀어보겠다.
좀 더 코테스러운 문제집을 골라왔다.

13460. 구슬 탈출 2

참고 여부 : X
소요 시간 : 1시간 30분

B자리에 R이 위치하게 될 때 B가 소실되는 문제점이 있었다. 이러한 TC를 찾느라 시간을 너무 많이 소비하였다.

다른 사람이 올려놓은 테케로 발견할 수 있었는데, 스스로 발견하지 못한 점이 아쉽다..

정답 코드

n, m = map(int, input().split())
origin_arr = []

R = [0, 0]
B = [0, 0]
hole = [0, 0]
for _ in range(n) :
    tmp = input()
    # origin_arr.append(list(input()))
    index_r = tmp.find('R')
    if (index_r != -1) :
        R = [_, index_r]
    index_b = tmp.find('B')
    if (index_b != -1) :
        B = [_, index_b]
    index_hole = tmp.find('O')
    if (index_hole != -1) :
        hole = [_, index_hole]
    origin_arr.append(list(tmp))

visited = set() # visited에 넣을땐 tuple로 넣기!
q = []
direction = [[-1, 0], [1, 0], [0, -1], [0, 1]] # 상하좌우
result = 9999999

current_r = R
current_b = B
q.append([R, B, 0])
visited.add(tuple([*R, *B]))
before_r = [0, 0]
before_b = [0, 0]

while (q) :
    before_r = [current_r[0], current_r[1]]
    before_b = [current_b[0], current_b[1]]

    current_r, current_b, cnt = q.pop(0)
    origin_arr[before_r[0]][before_r[1]] ='.'
    origin_arr[current_r[0]][current_r[1]] = 'R'
    if (origin_arr[before_b[0]][before_b[1]] != 'R') : 
        origin_arr[before_b[0]][before_b[1]] ='.'
    origin_arr[current_b[0]][current_b[1]] = 'B'
    
    cnt += 1
    if (cnt > 10) :
        continue
    for dd in direction :
        flag_r = False
        flag_b = False
        frontB = False

        # 움직이고자 하는 방향에서 B가 먼저인지 파악
        tmpy = current_r[0]
        tmpx = current_r[1]
        while (0 < tmpy + dd[0] < n - 1 and 0 < tmpx + dd[1] < m - 1) :
            if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == '.') :
                tmpy += dd[0]
                tmpx += dd[1]
            if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == 'B') :
                frontB = True
                break
            if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == '#') :
                break
            if (origin_arr[tmpy + dd[0]][tmpx + dd[1]] == 'O') :
                break
        if not (frontB) :
            yy, xx = current_r

            while (0 < yy + dd[0] < n - 1 and 0 < xx + dd[1] < m - 1) :
                if ((origin_arr[yy + dd[0]][xx + dd[1]] == '.') or (origin_arr[yy + dd[0]][xx + dd[1]] == 'O')) :
                    yy += dd[0]
                    xx += dd[1]
                    if (origin_arr[yy][xx] == 'O') :
                        flag_r = True
                        break
                else :
                    break
            origin_arr[current_r[0]][current_r[1]] = '.'
            if not flag_r:
                origin_arr[yy][xx] = 'R'
            y, x = current_b
            while ((0 < y + dd[0] < n - 1 and 0 < x + dd[1] < m - 1) and 
                    (origin_arr[y + dd[0]][x + dd[1]] == '.' or origin_arr[y + dd[0]][x + dd[1]] == 'O')) :
                y += dd[0]
                x += dd[1]
                if (origin_arr[y][x] == 'O') :
                    flag_b = True
                    break
            origin_arr[current_b[0]][current_b[1]] = '.'
            if not flag_b :
                origin_arr[y][x] = 'B'
        
        else :
            y, x = current_b
            while ((0 < y + dd[0] < n - 1 and 0 < x + dd[1] < m - 1) and 
                    (origin_arr[y + dd[0]][x + dd[1]] == '.' or origin_arr[y + dd[0]][x + dd[1]] == 'O')) :
                y += dd[0]
                x += dd[1]
                if (origin_arr[y][x] == 'O') :
                    flag_b = True
                    break
            origin_arr[current_b[0]][current_b[1]] = '.'
            if not flag_b :
                origin_arr[y][x] = 'B'
            yy, xx = current_r
            while (0 < yy + dd[0] < n - 1 and 0 < xx + dd[1] < m - 1) :
                if ((origin_arr[yy + dd[0]][xx + dd[1]] == '.') or (origin_arr[yy + dd[0]][xx + dd[1]] == 'O')) :
                    yy += dd[0]
                    xx += dd[1]
                    if (origin_arr[yy][xx] == 'O') :
                        flag_r = True
                        break
                else :
                    break
            origin_arr[current_r[0]][current_r[1]] = '.'
            if not flag_r:
                origin_arr[yy][xx] = 'R'

        if (flag_r and not flag_b) :
            result = min(result, cnt)
        elif not (flag_b) :
            if not tuple([yy, xx, y, x]) in visited :
                visited.add(tuple([yy, xx, y, x]))
                q.append([[yy, xx], [y, x], cnt])
        
        if (origin_arr[yy][xx] == 'R') :
            origin_arr[yy][xx] = '.'
            origin_arr[current_r[0]][current_r[1]] = 'R'
        elif (origin_arr[yy][xx] == 'O') :
            origin_arr[current_r[0]][current_r[1]] = 'R'

        if (origin_arr[y][x] == 'B') :
            origin_arr[y][x] = '.'
            origin_arr[current_b[0]][current_b[1]] = 'B'
        elif (origin_arr[y][x] == 'R') :
            origin_arr[current_b[0]][current_b[1]] = 'B'
        elif (origin_arr[y][x] == 'O') :
            origin_arr[current_b[0]][current_b[1]] = 'B'

if result == 9999999 :
    print(-1) 
else :
    print(result)

2048(easy)

참고 여부 : X
소요 시간 : 1시간 30분

up 방향의 함수를 하나 짜고 배열을 회전해서 인풋으로 넣어주려 하였다.
그런데 4개의 함수를 다 짜고 나서야 실수를 했다는 것을 깨달았다..

2 0 2
0 0 0
2 0 2

위의 배열에서 up 방향으로 움직이면

4 0 4
0 0 0
0 0 0

이러한 모양이 되어야하는데, 인접한 수만 고려하도록 짰다. 그래서 갈아엎었다.

이 문제에서 가장 헷갈리고 어려웠던건 배열을 원하는 방향으로 뒤집는 것이었다.
"zip(*arr)"을 통해서 transpose를 할 수 있다. Numpy를 쓰기엔 너무 낭비같다.

arr = list(map(list,zip(*arr)))
이렇게 하면 쉽게 전치 행렬을 얻을 수 있다.

  • 확실히 numpy가 좋긴하다.. 내장 함수도 많고 직관적이다. 코테에서 쓸 수 있는지는 찾아봐야겠다.

참고 여부 : X
소요 시간 : 1시간 40분

뱀의 꼬리를 컨트롤하는게 생각보다 어려웠다..

5
2
2 5
2 4
6
4 D
5 D
6 D
7 D
8 D
9 D

해당 반례를 통해 내가 어디서 실수했는지 알 수 있었다.
뱀의 몸통을 1만으로 구성하고, 상하좌우를 탐색해 1이 있으면 그곳을 꼬리로 잡았는데

1 0
1 1

뱀이 이러한 꼴을 하고 있을 때 꼬리를 제대로 잡지 못하였다.
이를 보완하기 위해 뱀의 몸통을 current_time + 1로 하였다.

맨날 히든 테케에서 걸리는데.. 나 취업 가능?


# 사과 = -1

timer = 0
direction = [[-1, 0], [0, 1], [1, 0], [0, -1]]
current_dir = 1

N = int(input())
arr = [[0] * N for _ in range(N)]
arr[0][0] = 1

k = int(input())
for _ in range(k) :
    y, x = map(int, input().split())
    arr[y - 1][x - 1] = -1

l = int(input())
change_time = []
for _ in range(l) :
    x, c = input().split()
    x = int(x)
    change_time.append([x, c])

snake_head = [0, 0]
snake_tail = [0, 0]
current_time = -1
x, c = change_time.pop(0)

while (True) :
    current_time += 1
    # 시간 체크하면서 방향 바꾸기
    if (x == current_time) :
        if (c == 'D') :
            current_dir = (current_dir + 1) % 4
        if (c == 'L') :
            current_dir = (current_dir - 1) % 4
        if (len(change_time) > 0) :
            x, c = change_time.pop(0)

    # 만약 벽이나 자기자신의 몸과 부딪히면 게임이 끝난다.
    if not ((0 <= snake_head[0] + direction[current_dir][0] < N) and (0 <= snake_head[1] + direction[current_dir][1] < N)) :
        break
    elif (arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] != 0
          and arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] != -1):
        break
    
    apple = False
    if (arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] == -1) :
        apple = True
    # 뱀의 머리를 방향대로 늘림.
    arr[snake_head[0] + direction[current_dir][0]][snake_head[1] + direction[current_dir][1]] = (current_time + 1)
    snake_head = [snake_head[0] + direction[current_dir][0], snake_head[1] + direction[current_dir][1]]
    
    # 사과를 먹지 않았다면 꼬리 줄이기.
    if not apple :
        arr[snake_tail[0]][snake_tail[1]] = 0
        minValue = 999999
        tail_4 = [999999] * 4

        idx = 0
        for dd in direction :
            if (0 <= snake_tail[0] + dd[0] < N and 0 <= snake_tail[1] + dd[1] < N) :
                if ((arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] != 0) or (arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] != -1)) :
                    if (arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] == 0 or arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]] == -1) :
                        idx += 1
                        continue
                    else :
                        tail_4[idx] = arr[snake_tail[0] + dd[0]][snake_tail[1] + dd[1]]
                        idx += 1
            else :
                idx += 1
        idx = tail_4.index(min(tail_4))
        snake_tail = [snake_tail[0] + direction[idx][0], snake_tail[1] + direction[idx][1]]
        
print(current_time + 1)

주사위 굴리기

참고 여부 : O
소요 시간 : 1시간

일단 주사위를 굴리는걸 구현한다는게 너무 어려웠다.
방법이 떠오르질 않아서 구글링을 하게 되었다. (세상엔 참 똑똑한 사람들이 많은 것 같다..)

방향을 돌려주는 매커니즘을 알아내서 굴린다음의 주사위를 업데이트 해주면 되는 것이었다.

이 방법을 알고나니 구현까진 수월했다. 그런데 "출력 초과"라는 결과가 나왔다.
난 디버거로 디버깅을 하는 편이라 코드 실수는 아닐 터였다..
한참을 살피다가 질문 게시판에도 올려보고, 챗 지피티랑 얘기도 해봤다.

앆! 발견했다. 지도에 주사위 아랫면을 업데이트 해줄 때 실수를 한 것이었다.
arr[y][x] = dice라고 써놓았다. 이를 arr[y][x] = dice[5]로 바꿔주니 바로 맞았다.


dice = [0] * 6

def turn(direct, y, x) :
    global dice
    global arr
    a, b, c, d, e, f = dice
    if (direct == 1) :
        dice[0] = d
        dice[2] = a
        dice[3] = f
        dice[5] = c
    if (direct == 2) :
        dice[0] = c
        dice[2] = f
        dice[3] = a
        dice[5] = d
    if (direct == 3) :
        dice[0] = e
        dice[1] = a
        dice[4] = f
        dice[5] = b
    if (direct == 4) :
        dice[0] = b
        dice[1] = f
        dice[4] = a
        dice[5] = e
    
    if (arr[y][x] != 0) :
        dice[5] = arr[y][x]
        arr[y][x] = 0
    else :
        arr[y][x] = dice[5]


n, m, x, y, k = map(int, input().split())

arr = []
for _ in range(n) :
    arr.append(list(map(int, input().split())))
commend = list(map(int, input().split()))

current_x = y
current_y = x
direction = [[0, 1], [0, -1], [-1, 0], [1, 0]] # 동서북남 -> 오 왼 위 아래 
for i in range(k) :
    # 먼저 갈 수 있는 곳인지 판단. 아니라면 넘김
    yy = direction[commend[i] - 1][0]
    xx = direction[commend[i] - 1][1]
    if not (0 <= current_x + xx < m and 0 <= current_y + yy < n) :
        continue
    current_y += yy
    current_x += xx
    turn(commend[i], current_y, current_x)
    print(dice[0])

로봇 청소기

참고 여부 : X
소요 시간 : 36분

조건에 맞게 천천히 구현하면 되는 문제였다.
그런데.. 자가 수정을 거치는 바람에 시간이 좀 더 걸렸다. 반시계 방향을 회전한 다음 탐색을 하는 것인데, 현 방향부터 탐색을 하도록 하였다.
이 부분을 수정하니 바로 맞힐 수 있었다.

n, m = map(int, input().split())
r, c, d = map(int, input().split())

arr = []
for _ in range(n) :
    arr.append(list(map(int, input().split())))

direction = [[-1, 0], [0, 1], [1, 0], [0, -1]]

current_y = r 
current_x = c
direction_idx = d

cnt = 0

while (True) :
    if (arr[current_y][current_x] == 0) :
        arr[current_y][current_x] = -1
        cnt += 1

    all_clean = True
    # 주변의 4칸 탐색
    for dd in range(1, 5, 1) :
        yy, xx = direction[(direction_idx - dd) % 4]
        if not (0 <= current_x + xx < m and 0 <= current_y + yy < n) :
            continue
        if (arr[current_y + yy][current_x + xx] == 0) :
            direction_idx = (direction_idx - dd) % 4
            current_y += yy
            current_x += xx
            all_clean = False
            break
    if all_clean :
        yy, xx = direction[(direction_idx - 2) % 4]
        if not (0 <= current_x + xx < m and 0 <= current_y + yy < n) :
            continue
        if (arr[current_y + yy][current_x + xx] != 1) :
            current_y += yy
            current_x += xx
        elif (arr[current_y + yy][current_x + xx] == 1) :
            break
print(cnt)

큐빙

참고 여부 : X
소요 시간 : 3시간.. 넘게?

앞전에 주사위 문제를 풀었던 방식으로 풀면 되겠다 싶었다.
총 12개의 함수를 만들어주면 되겠다는 생각을 했는데..
내가 너무 안일했는지 처음부터 꼼꼼히 만들지 않아서 그걸 고치느라 꽤 고생했다.
이런 시뮬레이션 문제의 경우, 모든 경우의 수를 꼼꼼히 따지고 구현하는 것이 더 효율적일 것 같다는 생각이 들었다.

내가 실수했던 부분은 U+에서 돌릴때 배열을 뒤집어서 적용해줘야하는 것이다. 다른 경우에서도 마찬가지고..
단순한 예제만으로는 잡아낼 수가 없는 부분이었다.

아 그리고.. https://rubiks-cube-solver.com/fr/
이 사이트를 활용해서 문제를 풀면 편하다. 나는 한참뒤에 알아내서 시간이 너무 아까웠다.
근데 코테에서는 이런 페이지 사용을 허용하지 않을 것 같아서 손으로 풀어본게 나쁘지만은 않았다.

풀고 나서 보니 플레5 문제라서 아주 뿌듯했다. 내 첫 플레..

def turn_clock_reverse_way(idx) :
    global cube
    cube[idx] = [list(x) for x in zip(*cube[idx])][::-1]

def turn_clock_way(idx) :
    global cube
    cube[idx] = [list(x) for x in zip(*(cube[idx][::-1]))]

def l_minus() :
    global cube
    turn_clock_reverse_way(3)
    o = [row[0] for row in cube[2]]
    w = [row[0] for row in cube[0]]
    r = [row[0] for row in cube[4]]
    y = [row[0] for row in cube[5]]

    for i in range(3) :
        cube[2][i][0] = w[i]
        cube[0][i][0] = r[i]
        cube[4][i][0] = y[i]
        cube[5][i][0] = o[i]

def l_plus() :
    global cube
    turn_clock_way(3)
    o = [row[0] for row in cube[2]]
    w = [row[0] for row in cube[0]]
    r = [row[0] for row in cube[4]]
    y = [row[0] for row in cube[5]]

    for i in range(3) :
        cube[4][i][0] = w[i]
        cube[5][i][0] = r[i]
        cube[2][i][0] = y[i]
        cube[0][i][0] = o[i]

def r_minus() :
    global cube
    turn_clock_reverse_way(1)
    o = [row[2] for row in cube[2]]
    w = [row[2] for row in cube[0]]
    r = [row[2] for row in cube[4]]
    y = [row[2] for row in cube[5]]

    for i in range(3) :
        cube[4][i][2] = w[i]
        cube[5][i][2] = r[i]
        cube[2][i][2] = y[i]
        cube[0][i][2] = o[i]
def r_plus() :
    global cube
    turn_clock_way(1)
    o = [row[2] for row in cube[2]]
    w = [row[2] for row in cube[0]]
    r = [row[2] for row in cube[4]]
    y = [row[2] for row in cube[5]]

    for i in range(3) :
        cube[2][i][2] = w[i]
        cube[0][i][2] = r[i]
        cube[4][i][2] = y[i]
        cube[5][i][2] = o[i]

def b_plus() :
    global cube
    turn_clock_way(2)
    w = cube[0][0]
    g = cube[3][0][::-1]
    y = cube[5][2][::-1]
    b = cube[1][0]

    cube[3][0] = w
    cube[0][0] = b
    cube[1][0] = y
    cube[5][2] = g

def b_minus() :
    global cube
    turn_clock_reverse_way(2)
    w = cube[0][0]
    g = cube[3][0]
    y = cube[5][2][::-1]
    b = cube[1][0][::-1]

    cube[3][0] = y
    cube[0][0] = g
    cube[1][0] = w
    cube[5][2] = b

def u_plus() :
    global cube
    turn_clock_way(0)
    r = cube[4][0]
    o = cube[2][2]
    b = [row[2] for row in cube[3]][::-1]
    g = [row[0] for row in cube[1]][::-1]

    for i in range(3) :
        cube[1][i][0] = o[i]
    cube[4][0] = g
    for i in range(3) :
        cube[3][i][2] = r[i]
    cube[2][2] = b

def u_minus() :
    global cube
    turn_clock_reverse_way(0)
    r = cube[4][0][::-1]
    o = cube[2][2][::-1]
    b = [row[2] for row in cube[3]]
    g = [row[0] for row in cube[1]]

    for i in range(3) :
        cube[1][i][0] = r[i]
    cube[2][2] = g
    for i in range(3) :
        cube[3][i][2] = o[i]
    cube[4][0] = b

def f_plus() :
    global cube
    turn_clock_way(4)
    b = cube[3][2]
    w = cube[0][2]
    g = cube[1][2][::-1]
    y = cube[5][0][::-1]

    cube[1][2] = w
    cube[5][0] = g
    cube[3][2] = y
    cube[0][2] = b

def f_minus() :
    global cube
    turn_clock_reverse_way(4)
    b = cube[3][2][::-1]
    w = cube[0][2]
    g = cube[1][2]
    y = cube[5][0][::-1]

    cube[1][2] = y
    cube[5][0] = b
    cube[3][2] = w
    cube[0][2] = g

def d_plus() :
    global cube
    r = cube[4][2][::-1]
    g = [row[0] for row in cube[3]]
    b = [row[2] for row in cube[1]]
    o = cube[2][0][::-1]

    turn_clock_way(5)
    for i in range(3) :
        cube[1][i][2] = r[i]
    cube[2][0] = b
    for i in range(3) :
        cube[3][i][0] = o[i]
    cube[4][2] = g

def d_minus() :
    global cube
    r = cube[4][2]
    g = [row[0] for row in cube[3]][::-1]
    b = [row[2] for row in cube[1]][::-1]
    o = cube[2][0]

    turn_clock_reverse_way(5)
    for i in range(3) :
        cube[1][i][2] = o[i]
    cube[4][2] = b
    for i in range(3) :
        cube[3][i][0] = r[i]
    cube[2][0] = g
t = int(input())
for _ in range(t) :
    n = int(input())
    commend = list(input().split())

    cube = [
        [['w'] * 3 for _ in range(3)],
        [['b'] * 3 for _ in range(3)],
        [['o'] * 3 for _ in range(3)],
        [['g'] * 3 for _ in range(3)],
        [['r'] * 3 for _ in range(3)],
        [['y'] * 3 for _ in range(3)],
    ]
    for i in range(n) :
        if commend[i] == 'L+' :
            l_plus()
        elif commend[i] == 'L-' :
            l_minus()
        elif commend[i] == 'R+' :
            r_plus()
        elif commend[i] == 'R-' :
            r_minus()
        elif commend[i] == 'U+' :
            u_plus()
        elif commend[i] == 'U-' :
            u_minus()
        elif commend[i] == 'D+' :
            d_plus()
        elif commend[i] == 'D-' :
            d_minus()
        elif commend[i] == 'F+' :
            f_plus()
        elif commend[i] == 'F-' :
            f_minus()
        elif commend[i] == 'B+' :
            b_plus()
        elif commend[i] == 'B-' :
            b_minus()
    for row in cube[0] :
        print(*row, sep='')

"""
4
12
D+ L+ B+ U+ R+ F+ D- L- B- U- R- F-
12
D- L- B- U- R- F- D+ L+ B+ U+ R+ F+
12
F+ R+ U+ B+ L+ D+ F- R- U- B- L- D-
12
F- R- U- B- L- D- F+ R+ U+ B+ L+ D+
"""

주석 처리되어있는 예제가 아주 효과적으로 디버깅 가능하다.
이러한 예제를 짜는 것도 연습을 해야겠다.

0개의 댓글

관련 채용 정보