프로그래밍 공부
작성일
2024. 3. 19. 15:20
작성자
WDmil
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개인 경우입니다.

입출력 예

rectangle characterX  characterY itemX itemY result
[[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보다 작은 거리로 먼저 탐색한 뒤에 이동해야 할것이다.


첫 번째 시도

#include <string>
#include <vector>

using namespace std;

bool InLine(vector<int>& Rect, vector<float>& item)
{
    // IN_Rect_Chack
    if (item[0] > Rect[0] && item[0] < Rect[2] && item[1] > Rect[1] && item[1] < Rect[3])
        return true;
    return false;
}

bool OnLine(vector<int>& Rect, vector<float>& item)
{
    // L_Line_Chack
    if (item[0] == Rect[0] && (item[1] >= Rect[1] && item[1] <= Rect[3]))
        return true;
    // R_Line_Chack
    else if (item[0] == Rect[2] && (item[1] >= Rect[1] && item[1] <= Rect[3]))
        return true;
    // U_Line_Chack
    else if (item[1] == Rect[3] && (item[0] >= Rect[0] && item[0] <= Rect[2]))
        return true;
    // D_Line_Chack
    else if (item[1] == Rect[1] && (item[0] >= Rect[0] && item[0] <= Rect[2]))
        return true;

    return false;
}

int solution(vector<vector<int>> rectangle, int characterX, int characterY, int itemX, int itemY) {
    vector<vector<int>> MovePoint = { {0, 1}, {1, 0}, {-1, 0}, {0, -1} };
    vector<int> item({ itemX, itemY });
    vector<int> UC({ characterX, characterY });
    vector<int> DC({ characterX, characterY });
    vector<int> UC_Back(UC);
    vector<int> DC_Back(DC);

    int result = 0;
    while (UC != item && DC != item) {

        bool OnLine_Chack = false;
        bool Collision_Chack = false;
        vector<float> MoveNext;
        for (int i = 0; i < MovePoint.size(); i++) {
            if (UC_Back[0] == UC[0] + MovePoint[i][0] &&
                UC_Back[1] == UC[1] + MovePoint[i][1]) continue;
            OnLine_Chack = false;
            Collision_Chack = false;
            MoveNext.resize(0);
            MoveNext.emplace_back(UC[0] + MovePoint[i][0] * 0.5);
            MoveNext.emplace_back(UC[1] + MovePoint[i][1] * 0.5);
            for (auto& Rect : rectangle)
            {
                if (!OnLine_Chack) OnLine_Chack = OnLine(Rect, MoveNext);
                Collision_Chack = InLine(Rect, MoveNext);
                if (Collision_Chack) break;
            }
            if (!Collision_Chack && OnLine_Chack)
            {
                UC_Back = UC;
                UC[0] += MovePoint[i][0];
                UC[1] += MovePoint[i][1];
                break;
            }
        }
        for (int i = MovePoint.size() - 1; i >= 0; i--) {
            if (DC_Back[0] == DC[0] + MovePoint[i][0] &&
                DC_Back[1] == DC[1] + MovePoint[i][1]) continue;
            OnLine_Chack = false;
            Collision_Chack = false;
            MoveNext.resize(0);
            MoveNext.emplace_back(DC[0] + MovePoint[i][0] * 0.5);
            MoveNext.emplace_back(DC[1] + MovePoint[i][1] * 0.5);
            for (auto& Rect : rectangle)
            {
                if (!OnLine_Chack) OnLine_Chack = OnLine(Rect, MoveNext);
                Collision_Chack = InLine(Rect, MoveNext);
                if (Collision_Chack) break;
            }
            if (!Collision_Chack && OnLine_Chack)
            {
                DC_Back = DC;
                DC[0] += MovePoint[i][0];
                DC[1] += MovePoint[i][1];
                break;
            }
        }
        result++;
    }
    return result;
}

성공

 

그냥 사각형을 전부 탐색하면서, 이동해야하는 위치의 Up Down, Left, Right의 위치값이 사각형의 선분 위에 존재하는지, 그리고 사각형의 내부에 들어가는지를 확인하고, 올바르다면 이동, 아니라면 이동하지 않으면 된다.

 

또한, 위 또는 아래로 이동했을 때 가장 짧은 거리를 리턴하는 방법은, 두개를 동시에 탐색시키면 된다.

728x90

'코딩테스트 문제 풀이 > 깊이&너비 우선탐색(DFS&BFS)' 카테고리의 다른 글

리코쳇 로봇  (1) 2024.03.27
여행경로  (0) 2024.03.20
(2019 KAKAO BLIND RECRUITMENT)길 찾기 게임  (0) 2024.03.05
단어 변환  (0) 2024.02.22
게임 맵 최단거리  (0) 2024.02.22