하루일문

[SW] 1949번 등산로 조성 (파이썬) 본문

algorithm/sw

[SW] 1949번 등산로 조성 (파이썬)

support_u 2023. 2. 13. 00:41

포인트

1. 상하좌우 이동

2. 이동 값 초기화

3. 땅을 판 뒤 판 땅도 초기화

4. 함수 나온 뒤도 초기화

5. k를 무조건 다 쓸 필요 없이 지금 땅 보다만 작으면 됨

풀이

# 상하좌우로 이동
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]

# 함수
# 값을 가져올것
def dsf(I, J, K):
    # 글로벌에서 바꿔가면서 가져갈것
    global MaX, visited
    # 멀리 갈 수록 높아지게 설정
    MaX = max(MaX, visited[I][J])

    # 상하 좌우로 이동하면서 본다
    for im in range(4):
        mx = I + dx[im]
        my = J + dy[im]

        # 표 안에 있으면서 visited에서 이미 갔다는 표시가 없는곳
        if 0 <= mx < n and 0 <= my < n and visited[mx][my] == 0:
            # 그냥 갈 수 있는 경우(작은 경우)
            if mountain[I][J] > mountain[mx][my]:
                # 원래 있던 장소보다 1 더한다
                # 별도로 수를 넣었을때 초기화를 한번 더 넣어줘야해서 뺌
                visited[mx][my] = visited[I][J] + 1
                # 걸어간 곳에서 다시 함수 실행
                dsf(mx, my, K)

                # 갈림길에서 빠져나올때 visited에서 지나올 길을 0으로 초기화
                visited[mx][my] = 0

            else:
                # 큰 곳 중 땅을 파면 갈 수 있는곳
                if K != 0 and mountain[I][J] > mountain[mx][my] - K:
                    # 땅을 파기전에 돌아갈 때를 생각해서 파기전 땅을 저장
                    temp = mountain[mx][my]
                    # 지금있는 땅보다 -1만 더 판다
                    mountain[mx][my] = mountain[I][J] - 1
                    visited[mx][my] = visited[I][J] + 1
                    dsf(mx, my, 0)

                    # 갈림길에서 빠져나올때 판 땅을 돌려놓고 지나간 자리를 0으로 초기화 
                    mountain[mx][my] = temp
                    visited[mx][my] = 0



# 입력
T = int(input())
for t in range(1, T + 1):
    n, k = map(int, input().split())
    mountain = [list(map(int, input().split())) for _ in range(n)]
    visited = [[0] * n for _ in range(n)]

    # 높은 봉우리 찾기
    maxi = []
    for N in mountain:
        maxi.append(max(N))
    start = max(maxi)

    # 가장 높은 곳을 찝하줄 값(for안에 들어가면 초기화가 돼서 안됨)
    MaX = 0
    # 산 중 가장 높은곳에서 시작(높은 곳은 중복)
    for i in range(n):
        for j in range(n):
            if mountain[i][j] == start:
                visited[i][j] = 1
                dsf(i, j, k)
                # 함수에서 나오고 0으로 초기화
                visited[i][j] = 0

    print(f'#{t} {MaX}')

회고

처음엔 dsf라고 생각하면서 visited를 안쓰고 가다가 땅 파기 전까지는 값이 나왔지만 땅 파면 자기 멋대로 돌아다녀서 코드를 다시 짜게 되었다.
카운트도 따로 받다가 초기화를 하지 못하고 무작전 커지다가 visited에 수를 넣기로 했다.
초기화를 하는 법을 모르겠어서 마지막엔 코드를 찾아서 작성했다.
그 이후 또 값이 안 맞길래 찾아보니 무작전 k번을 다 파면 안된다는 것을 알고 그것도 수정하여 겨우 맞출 수 있었다.

필수로 다시 봐야할 것 같은 문제다