본문 바로가기

프로그래머스 코테 연습/위클리 챌린지

위클리 챌린지 #5. 아이템 줍기

728x90

(문제 설명)

다음과 같은 다각형 모양 지형에서 캐릭터가 아이템을 줍기 위해 이동하려 합니다.

지형은 각 변이 x축, y축과 평행한 직사각형이 겹쳐진 형태로 표현하며, 캐릭터는 이 다각형의 둘레(굵은 선)를 따라서 이동합니다.

만약 직사각형을 겹친 후 다음과 같이 중앙에 빈 공간이 생기는 경우, 다각형의 가장 바깥쪽 테두리가 캐릭터의 이동 경로가 됩니다.

단, 서로 다른 두 직사각형의 x축 좌표 또는 y축 좌표가 같은 경우는 없습니다.

즉, 위 그림처럼 서로 다른 두 직사각형이 꼭짓점에서 만나거나, 변이 겹치는 경우 등은 없습니다.

다음 그림과 같이 지형이 2개 이상으로 분리된 경우도 없습니다.

한 직사각형이 다른 직사각형 안에 완전히 포함되는 경우 또한 없습니다.

지형을 나타내는 직사각형이 담긴 2차원 배열 rectangle, 초기 캐릭터의 위치 characterX, characterY, 아이템의 위치 itemX, itemY가 solution 함수의 매개변수로 주어질 때, 캐릭터가 아이템을 줍기 위해 이동해야 하는 가장 짧은 거리를 return 하도록 solution 함수를 완성해주세요.

제한사항
  • rectangle의 세로(행) 길이는 1 이상 4 이하입니다.
  • rectangle의 원소는 각 직사각형의 [좌측 하단 x, 좌측 하단 y, 우측 상단 x, 우측 상단 y] 좌표 형태입니다.
    • 직사각형을 나타내는 모든 좌표값은 1 이상 50 이하인 자연수입니다.
    • 서로 다른 두 직사각형의 x축 좌표, 혹은 y축 좌표가 같은 경우는 없습니다.
    • 문제에 주어진 조건에 맞는 직사각형만 입력으로 주어집니다.
  • charcterX, charcterY는 1 이상 50 이하인 자연수입니다.
    • 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.
  • itemX, itemY는 1 이상 50 이하인 자연수입니다.
    • 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.
  • 캐릭터와 아이템의 처음 위치가 같은 경우는 없습니다.

  • 전체 배점의 50%는 직사각형이 1개인 경우입니다.
  • 전체 배점의 25%는 직사각형이 2개인 경우입니다.
  • 전체 배점의 25%는 직사각형이 3개 또는 4개인 경우입니다.

입출력 예rectanglecharacterXcharacterYitemXitemYresult
[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]] 1 3 7 8 17
[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]] 9 7 6 1 11
[[1,1,5,7]] 1 1 4 7 9
[[2,1,7,5],[6,4,10,10]] 3 1 7 10 15
[[2,2,5,5],[1,3,6,4],[3,1,4,6]] 1 4 6 3 10
입출력 예 설명

입출력 예 #1

캐릭터 위치는 (1, 3)이며, 아이템 위치는 (7, 8)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.

입출력 예 #2

캐릭터 위치는 (9, 7)이며, 아이템 위치는 (6, 1)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.

입출력 예 #3

캐릭터 위치는 (1, 1)이며, 아이템 위치는 (4, 7)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.

입출력 예 #4, #5

설명 생략

 


(문제 해설)

 

# 0. 도형들의 끝 좌표들이 주어진다. 이 도형들 중에서 외곽의 선만을 어떻게 딸까?

# 1. 외곽의 선을 일일이 찾을 생각을 하지 말고, 주어진 도형들 안에 값들을 모두 1로 만들고

# 2. 그 다음 외곽 -1의 크기만큼 다시 0으로 만들면 외곽의 선만 딸 수 있을 거 같다

# 3. 그다음 stX, stY로 시작하고 not visited이고, 값이 1인 선을 쭉 따라서 탐색하면서 값을 이전 값 +=1을 하는 기초적인 그래프 문제처럼 풀면 문제를 풀 수 있을 것 같다.

 

# (~˘▾˘)~ : 중요사항: 이렇게 1을 따라 풀면 문제를 틀릴 것 입니다. 왜 그럴까요?

그림으로 설명하겠습니다.

 

그림_*2를 하는 이유

이점을 고려하여 코딩을 해봅시다

 


[코드]

 

# 5. 아이템 줍기
dx = [0, 0, -1, 1]
dy = [1, -1, 0, 0]
from collections import deque


def solution(rectangle, characterX, characterY, itemX, itemY):
    answer = 0
    stX = 2 * characterX
    stY = 2 * characterY
    descX = 2 * itemX
    descY = 2 * itemY

    visited = [[0] * 101 for _ in range(101)]
    visited[stX][stY] = 1
    q = deque([(stX, stY)])
    outskirts = [[0] * 101 for i in range(101)]

    # 외곽에 1로 표기
    for x1, y1, x2, y2 in rectangle:
        for i in range(2 * x1, 2 * x2 + 1):
            for j in range(2 * y1, 2 * y2 + 1):
                outskirts[i][j] = 1

    # 안쪽을 0으로 표기
    for x1, y1, x2, y2 in rectangle:
        for i in range(2 * x1 + 1, 2 * x2):
            for j in range(2 * y1 + 1, 2 * y2):
                outskirts[i][j] = 0

    # print(len(outskirts))
    # bfs 이용
    while q:
        x, y = q.popleft()

        # 아이템 위치 도착
        if x == descX and y == descY:
            answer = (outskirts[x][y]) // 2
            break

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < len(outskirts) and 0 <= ny < len(outskirts):
                if outskirts[nx][ny] != 0 and visited[nx][ny] == 0:
                    outskirts[nx][ny] = outskirts[x][y] + 1
                    visited[nx][ny] = 1
                    q.append([nx, ny])


    # for o in outskirts:
    #     print(o)
    return answer

후기

 

외곽선을 일일이 찾아서 따려고 하면 막히기 십상입니다..(경험)

간단하게 생각하는 것도 방법입니다.

또 *2를 하는 기법은 자주 이용하는 기법이니 머릿속에서 생각해두시기를 바랍니다.

728x90