본문 바로가기

자료구조 & 알고리즘/알고리즘

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

1. 목표 지점까지 테두리를 시계 방향으로 이동 vs (반시계 방향 이동 ==   목표 지점에서 현 위치까지 시계 방향 이동)

 => 두개를 구해서 더 짧은걸 채용

2. 도달하지 못하는 경우는 없으므로 목표 지점에 도달 할 때까지 계속 반복 (while True)

3. 현재 좌표가 어떤 사각형 위에 있는지 봐야됨 (for rectangle in rectangles)

4. 현재 좌표가 어떤 사각형 위에 있다면 그 변을 따라서 계속 이동함 (while True)

5. 변을 이동한 좌표가 다른 사각형의 내부라면 다시 back하고 다른 사각형의 변을 따라 이동함 (while 문 break 이후 다시 for문으로 다른 rectangle 탐색)

5-1. 1씩 체크하는 경우 사각형의 변이 1이라면 내부를 뚫고 지나가는 경우가 생김 case2:( [[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]])

     >> 이를 해결하기 위해 0.5만 이동해서 그 좌표가 사각형 내부인지 확인함(0.5가 아니어도 됨 1보다 작기만하면됨)

 

6. a)좌표가 사각형 내부에 있는 판별하는 함수, b)좌표의 위치에 따라 어느 방향으로 이동할지 판별하는 함수 작성

6-1.b)를 하기 싫으면 그냥 4방향으로 다 이동하고 확인하면됨

 

def solution(rectangles, characterX, characterY, itemX, itemY):
    # 시계 방향 vs 반시계 방향 (케릭터=> item 시계 방향 vs item=> 케릭터 시계 방향)
    return min(solution1(rectangles, characterX, characterY, itemX, itemY), solution1(rectangles, itemX, itemY, characterX, characterY))


def solution1(rectangles, characterX, characterY, itemX, itemY):
    answer = 0
    # 한점은 최대 두 사각형만 교차 가능함
    while True:
        for rectangle in rectangles:
            # 점이 사각형 변위에 있고 사각형 내부가 아닐 경우 계속 반복
            while True:
                # result : None / x, y
                result = is_at_rectangle_line(rectangle, characterX, characterY)

                # 현재 점이 변위에 있으면 이동
                if result:
                    characterX += result[0]
                    characterY += result[1]
                    answer += 1
                    if characterX == itemX and characterY == itemY:
                        return answer

                    # 옮긴점이 다른 사각형 내부라면 다시 back하고 다른 사각형 변위에서 이동
                    # 변의 길이가 1이면 옮긴전이 내부가 아니고 변에 위치하는 경우가 생김, 하지만 사각형을 뚫고 지나가는 경우가 생김
                    # 해결법 =>  1씩 이동하지 않고 0.5만큼 이동해서 내부인지 확인하고 내부가 아니면 1을 이동한단 마인드
                    if is_in_rectangle(rectangles, characterX-(result[0]/2), characterY-(result[1]/2)):
                        # 케릭터 좌료 원상 복구
                        characterX -= result[0]
                        characterY -= result[1]
                        answer -= 1

                        # 다음 사각형으로 이동
                        break
                # 점이 사각형 변위에 없으면 다른 사각형 탐색
                else:
                    break

    return answer


# 점(x,y)이 다른 사각형 안에 있는지 판별
def is_in_rectangle(rectangles, x, y):
    for x1, y1, x2, y2 in rectangles:
        if is_at_rectangle_line([x1, y1, x2, y2], x, y):
            pass
        # 변위에 있지 않고 사각형 내부에 있을 경우
        elif x1 <= x <= x2 and y1 <= y <= y2:
            return True
    return False


# 점(x,y)이 사각형 변에 있는지 판별 후 이동할 좌표 return / None
# 무조건 시계 방향으로 탐색
def is_at_rectangle_line(rectangle, x, y):
    x1, y1, x2, y2 = rectangle

    if x == x1 and y1 <= y < y2:
        return 0, 1

    elif x == x2 and y1 < y <= y2:
        return 0, -1

    elif x1 < x <= x2 and y == y1:
        return -1, 0

    elif x1 <= x < x2 and y == y2:
        return 1, 0

    else:
        return None