[알고리즘] 프로그래머스 49994

은개·2025년 2월 16일

[CS] 알고리즘

목록 보기
11/21

💡

문제가 요구하는 조건을 생각하고, 이를 함수로 쪼개서 구현하는 게 실수를 줄일 수 있는 방법인 듯
예를 들어, 문제에서 어떤 정렬 조건과 예외 처리 조건이 주어질 때, sort에 람다함수를 사용하는 것 대신 함수를 따로 만들어서 sort의 비교 함수로 넣으면 더 가독성이 좋음

프로그래머스 - 방문 길이

오답

풀이

  • U: y++ / D: y--- / R: x++ / L: x--
  • dirs의 명령어대로 x, y를 증감 시키고 이를 set에 저장
  • set의 길이를 출력
  • 즉, 이동한 직선의 총 길이를 구하는 문제
#include <string>
#include <set>

using namespace std;

int solution(string dirs) {
    int answer = 0;
    int x = 0, y = 0;
    set<pair<int, int>> positions;

    for (int i = 0; i < dirs.length(); i++) {
        if (dirs[i] == 'U' && y < 5) {
            y++;
        }
        else if (dirs[i] == 'D' && y > -5) {
            y--;
        }
        else if (dirs[i] == 'R' && x < 5) {
            x++;
        }
        else if (dirs[i] == 'L' && x > -5) {
            x--;
        }
        
        positions.insert({x, y});
    }
    
    return positions.size();
}

🤓 실수
int x, y = 0;
x,y 둘 다 0으로 초기화 하려면 x = 0, y = 0 이렇게 해야하는데 저렇게 해서 y만 초기화 됨

dirs[i] == "U"
dirs[i]와 명령어를 비교할 때 char은 작은 따옴표를 사용해야 하는데 큰 따옴표를 사용해서 char와 const char*를 비교하는 꼴이 되어버림

💥 문제점
다른 길을 통해 다시 그 점에 돌아온 경우, 동일한 좌표이긴 하지만 다른 길이기 때문에 이 경우도 카운트를 해야 하는데 set을 써서 중복은 무조건 예외처리가 되어버림


교재 코드

#include <string>
#include <set>

using namespace std;

bool visited[11][11][4]; // 1. 특정 좌표에서 특정 방향으로 이동한 적이 있는지 체크

// 2. 상하좌우로 좌표를 이동할 때 필요한 좌표의 오프셋 배열
int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};

// 3. 각 문자에 해당하는 오프셋 배열의 인덱스를 반환
int todir(char dir) {
    int ret;
    if (dir == 'U')
        ret = 0;
    else if (dir = 'R')
        ret = 1;
    else if (dir = 'D')
        ret = 2;
    else
        ret = 3;

    return ret;
}

// 4. 특정 좌표가 주어진 좌표 평면을 벗어나는지 확인
bool isNotValid(int x, int y) { return x < 0 || y < 0 || x > 10 || y > 10; }

// 5. 현재와 반대 방향의 오프셋 배열 인덱스 반환
int opposite_direction(int dir) {return (dir + 2) % 4; }

int solution(string dirs) {
    int answer = 0;
    int x = 5, y = 5; // 6. 시작 좌표를 설정
    
    for (auto c : dirs) {
        // 7. 반복문을 순회하며 nx, ny는 x, y가 dirs대로 움직였을 때 위치가 됨
        int dir = todir(c);
        int nx = x + dx[dir];
        int ny = y + dx[dir];

        // 8. 좌표 평면을 벗어나면 더 이상 이동하지 않음
        if (isNotValid(nx, ny))
            continue;
        
        // 9. 다음 좌표가 아직 방문하지 않은 좌표인 경우
        if (visited[y][x][dir] == false) {
            // 10. 방문을 중복 체크하지 않도록 해당 경로의 양방향 방문을 체크
            visited[y][x][dir] = true;
            visited[ny][nx][opposite_direction(dir)] = true;
            answer++;
        }

        // 11. 현재 좌표를 이동한 좌표로 업데이트

        x = nx;
        y = ny;
    }
    
    return answer;
}

복습

#include <string>
#include <set>

using namespace std;

bool visited[11][11][4]; // 좌표, 상하좌우 방향 저장 (x, y 좌표를 1부터 10까지 저장할 것이기 때문에 11개 할당)

int todir(char dir) {
    if (dir == 'U') return 0;
    else if (dir == 'R') return 1;
    else if (dir == 'D') return 2;
    else return 3;
}

int opposite_dir(int dir) {
    return (dir + 2) % 4;
}

int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};

bool isNotValid(int x, int y) { return x < 0 || y < 0 || x > 10 || y > 10; }

int solution(string dirs) {
    int answer = 0;
    int x = 5, y = 5; // 시작 좌표 설정
    
    for (auto c : dirs) {
        int dir = todir(c); // 방향 인덱싱을 위해 dir을 int로 저장
        
        // x, y 좌표를 dir방향 오프셋만큼 이동
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        
        // continue 하면 기존 x, y를 업데이트 하지 않기 때문에 이동 처리 되지 않음
        if (isNotValid(nx, ny)) continue;
        
        if (visited[y][x][dir] == false) {
            visited[y][x][dir] = true; // 기존 좌표에서 다음 좌표로 가는 직선
            visited[ny][nx][opposite_dir(dir)] = true; // 다음 좌표에서 기존 좌표로 오는 직선
            answer++;
        }
        
        // 다음 좌표로 이동
        x = nx;
        y = ny;
    }
    
    return answer;
}

🤓 실수

int todir(char dir) {
    if (dir == 'U') return 0;
    else if (dir == 'D') return 1;
    else if (dir == 'R') return 2;
    else return 3;
}

dx, dy 배열은 [D(하), R(우), U(상), L(좌)] 순서로 되어있기 때문에 인덱스 리턴하는 것도 이 순서에 맞춰서 해야하는데 잘못된 방향 인덱스 리턴하게 구현해버림
근데 지금 보니까 책도 배열은 [D, R, U, L] 순서로 짜놓고 인덱싱 하는 건 [U, R, D, L] 순으로 했네,,,

이게 올바른 풀이

int todir(char dir) {
	if (dir == 'D') return 0;
    else if (dir == 'R') return 1;
    else if (dir == 'U') return 2;
    else return 3;
}

0개의 댓글