Algorithm/acmicpc.net

좌표를 헷갈리지 말 것!! (#14499 주사위 굴리기)

winney916 2024. 3. 23. 17:54
728x90

#14499 주사위 굴리기 https://www.acmicpc.net/problem/14499

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x, y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지

www.acmicpc.net

 

 

일단 주사위를 구현하는 것 부터가 빡셌다.

처음엔 리스트 두개로 구현하려고 했는데 리스트 간에 값을 교환하는 횟수가 너무 많을 것 같다는 생각이 들었다.

주사위가 동서남북으로 움직일 때마다 각 6면의 변화를 상상했다.

이렇게 변화하는 모습을 보였다.

(사실 처음에 잘못 판단해서 삽질을 좀 했다.)

 

따라서 주사위 구현은 정수형 자료형을 저장하는 6개 변수로 진행했다.

 

각 면의 방향에 따라 6개의 변수를 생성하고 주사위의 움직임을 추적한다.

 

그리고 제출했는데,

 

자꾸 시작도 못해보고 1%에서 틀린다.

 

그래서 이유를 찾아봤는데,,,,

지도에서 좌표를 표기하는 형태에서 오류가 있었다.

 

대부분이 그렇겠지만, 나는 지도를 표현할 때 2차원 리스트를 사용한다.

 

 

그리고 문제는 인덱싱인데, 2차원 리스트에 대한 인덱싱은 maps[a][b]로 진행된다.

이렇게 진행하면 다음과 같은 형태로 리스트에 접근하게 된다.

쉽게 표현하면, a가 세로축이 되고, b가 가로축이 된다.

나는 변수를 선언할 때 가로축 세로축을 각각 x, y로 표현한다.

 

따라서 파이썬 리스트 인덱싱을 진행할 때에는 다음과 같이 진행해야한다.

 

maps[y][x]

 

수학공부를 할 때 (x, y)라고 쓰는게 습관이 되어 있어서 헷갈리기 쉽다.

절대 헷갈리지 말자 절대!!

라며 매일 매일 다짐했다.

 

하지만.... 이번엔 새로운 이슈가 있었다.

입력을 받을 때 이렇게 받아버린 것이다.

하지만 실제 입력은 (나의 기준에서는) y, x순으로 들어오고 있었다.

 

하지만 테스트케이스는 모두 0,0에서 출발하는 경우였고 여기서 체크되지 않은 나의 실수는 실제 채점 시 1%에서 틀리는 참사로 이어진 것이다.

 

하.....

 

 

그렇게 완성된 나의 정답코드!

# get input
h, w, y, x, k = map(int, input().split())

# 지도의 각 칸에는 정수가 하나씩 쓰여져 있다.
maps = [[int(x) for x in input().split()] for _ in range(h)]
# 동 : 1, 서 : 2, 북 : 3, 남 : 4
cmds = [int(x) for x in input().split()]

# 가장 처음 주사위의 모든 면에 0이 적혀져 있다.
top = bott = nort = sout = west = east = 0


def valid_pos(x, y):  # 지도의 바깥인 경우
    global h, w
    # print(x, y)
    return (0 <= x < w) and (0 <= y < h)


while len(cmds):
    cmd = cmds.pop(0)

    if cmd == 1:  # move East
        nx, ny = x + 1, y

        if not valid_pos(nx, ny):  # 지도의 바깥인 경우 명령 무시
            continue

        x, y = nx, ny
        tmp = east
        top, west, east = west, bott, top

        # 0이 아닌 경우에는 칸에 쓰여있는 수가 주사위의 바닥면으로 복사되며 칸의 수는 0이 된다.
        if maps[y][x]:
            bott = maps[y][x]
            maps[y][x] = 0

        # 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
        else:
            bott = tmp
            maps[y][x] = bott

    elif cmd == 2:  # move west
        nx, ny = x - 1, y

        if not valid_pos(nx, ny):
            continue

        x, y = nx, ny
        tmp = west
        top, west, east = east, top, bott

        if maps[y][x]:
            bott = maps[y][x]
            maps[y][x] = 0
        else:  # 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
            bott = tmp
            maps[y][x] = bott

    elif cmd == 3:  # move north
        nx, ny = x, y - 1

        if not valid_pos(nx, ny):
            continue

        x, y = nx, ny
        tmp = nort
        top, nort, sout = sout, top, bott

        if maps[y][x]:
            bott = maps[y][x]
            maps[y][x] = 0
        else:  # 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
            bott = tmp
            maps[y][x] = bott

    elif cmd == 4:  # move south
        nx, ny = x, y + 1

        if not valid_pos(nx, ny):
            continue

        x, y = nx, ny

        tmp = sout
        top, nort, sout = nort, bott, top

        if maps[y][x]:
            bott = maps[y][x]
            maps[y][x] = 0
        else:  # 이동한 칸에 쓰여있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
            bott = tmp
            maps[y][x] = bott

    print(top)
    # print("cmd : ", cmd)
    # print(top, bott, nort, sout, west, east)

    # for m in maps:
    #     print(m)

 

틀릴 때 마다 검토하는건 굉장히 번거로우니

빡센 구현의 경우에는 문제에 나와있는 조건들을 주석으로 작성하면서 진행하는게 좋(았)다.

 

그럼 이만.

 

 

 

 

나의 알고리즘 문제풀이 Rule #1 : 지도 표현하기

지도는 2차원 리스트로 표현하고, position은 x, y로 표현한다.

따라서 접근 방법은 maps[y][x]로 설정한다. x와 y의 순서를 혼동하지 말자.

 

수학공부를 할 때 (x, y)라고 쓰는게 습관이 되어 있어서 헷갈리기 쉽다.

절대 헷갈리지 말자 절대!!