[프로그래머스] 아이템 줍기

mokomoko·2022년 5월 16일
0

1. 문제


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

지형은 각 변이 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개인 경우입니다.

- 키워드

  • 좌표 * 2 를 적용해보자.

2. 풀이


이 문제를 풀 때, 1번 테스트케이스에서 막히던 사람들이 꽤 많았던 거 같다. 나도 그랬다

그 이유를 살펴보자면

1번 테스트케이스에서 최단거리를 구하면 저렇게 나오는데

정답은 17이지만, 원초적으로 코드를 작성한 사람들은 15가 나왔을 것이다.

어딘가가 누락된 것인데 바로 이 부분이다.

원초적으로 작성했다면, 파란색 방향으로 갔을것이고,

본래 정답은 빨간색 방향으로 가야한다는 것이다.

다음 경로를 탐색할 때 거리가 1안에 있어서 이런 오류를 범하는데,

이런 오류를 피하기 위해서 좌표를 2씩 곱해서 계산하게 된다.

그렇게 한다면, 해당 오류를 피하고 결과값을 2로 나눠서 출력하면 된다.

3. 소스코드


from collections import deque

def solution(rectangle,characterX,characterY,itemX,itemY):
	board = [[0] * 101 for _ in range(101)]
	characterX,characterY = characterX*2,characterY*2
	itemX,itemY = itemX*2,itemY*2
	for i in rectangle:
		sr,sc,fr,fc = i
		sr,sc,fr,fc = sr*2,sc*2,fr*2,fc*2
		for row in range(sr,fr+1):
			for col in range(sc,fc+1):
				if (row == sr or row == fr or col == sc or col == fc) and board[row][col] != -1:
					board[row][col] = 1
				else:
					board[row][col] = -1
	q = deque()
	q.append([characterX,characterY])
	d = [(-1,0),(0,1),(1,0),(0,-1)]
	cnt = 0
	while q:
		next_q = deque()
		while q:
			row,col = q.popleft()
			board[row][col] = -1
			if row == itemX and col == itemY:
				return cnt // 2
			for i in d:
				drow,dcol = i
				if 0 <= row+drow < 101 and 0 <= col+dcol < 101:
					if board[row+drow][col+dcol] == 1:
						next_q.append([row+drow,col+dcol])
		q = next_q
		cnt += 1

if __name__ == "__main__":
	print(solution([[1, 1, 3, 3]], 1, 1, 1, 2))

4. 후기


좌표 * 2를 바로 떠올린다면, 누군가에게는 레벨 2

떠올리지 못했다면, 누군가에게는 레벨 3이상일 것이다.

난 후자였다.

0개의 댓글