[백준/C++] 6087번 레이저 통신

2022. 11. 15. 16:35·PS/C++
728x90

백준


🤔문제 이해

하나의 C에서 다른 C까지 가는 경로 중 방향을 가장 적게 바꾸면서 가는 방법을 찾아 방향을 바꾼 횟수를 출력하는 문제이다.


🔥풀이🔥

첫번째 C에서 갈 수 있는 경로를 먼저 탐색하여 각 방향별로 cnt를 0으로 queue에 넣어준다.

그 뒤에는 queue가 빌때까지 각 방향대로 돌면서 이전과 같은 방향인 경우 cnt는 그대로 두고, 다른 방향인 경우 cnt에 +1을 해주었다. 그렇게 처리한 cnt값이 dp의 값보다 작거나 같으면 dp를 업데이트해주고 queue에도 넣어주었다. 

queue에서 pop될 때 dp의 값이 cnt보다 작으면 continue을 해주어서 불필요한 연산을 줄여주었고, dp값이 cnt보다 큰 경우는 cnt로 업데이트 해주었다. 

 

✍️ 후기

처음엔 단순히 BFS를 해서 방향이 바뀔 때마다 cnt값을 +1해주는 방식으로 했지만 이렇게 하면 메모리 초과가 났다. 


#include <queue>
#include <iostream>

#define INF 1000000000

using namespace std;

int w, h;
char map[101][101];
int dp[101][101];
priority_queue<pair<pair<int, int>, pair<int, int>>> pq;
pair<int, int> start;
pair<int, int> ended;
int di[4] = {1, -1, 0, 0};
int dj[4] = {0, 0, 1, -1};


void BFS() {

    while (!pq.empty()) {
        int cnt = -pq.top().first.first;
        int direct = pq.top().first.second;
        int i = pq.top().second.first;
        int j = pq.top().second.second;
        pq.pop();

        if( dp[i][j] < cnt ) continue;
        dp[i][j] = cnt;
        
        for (int k = 0; k < 4; k++) {
            int ni = i + di[k];
            int nj = j + dj[k];
            if (ni < 0 || nj < 0 || ni >= h || nj >= w) continue;
            if (map[ni][nj] == '*') continue;

            int next_cnt = (direct == k) ? cnt : cnt + 1;
            if (dp[ni][nj] < next_cnt) continue;
            dp[ni][nj] = next_cnt;
            pq.push({{-next_cnt, k},
                     {ni,       nj}});
        }
    }
    cout << dp[ended.first][ended.second];
}

int main() {
    cin.tie(nullptr);
    cout.tie(nullptr);
    ios::sync_with_stdio(false);

    cin >> w >> h;
    string s;
    bool flag = false;
    for (int i = 0; i < h; i++) {
        cin >> s;
        for (int j = 0; j < s.size(); j++) {
            map[i][j] = s[j];
            if (s[j] == 'C') {
                if (!flag) {
                    start = {i, j};
                    flag = true;
                } else {
                    ended = {i, j};
                }
            }
        }
    }
    for (int i = 0; i < 101; i++) {
        for (int j = 0; j < 101; j++) {
            dp[i][j] = INF;
        }
    }

    dp[start.first][start.second] = 0;
    for (int k = 0; k < 4; k++) {
        int ni = start.first + di[k];
        int nj = start.second + dj[k];
        if (ni < 0 || ni >= h || nj < 0 || nj >= w) continue;
        if (map[ni][nj] == '*')continue;
        dp[ni][nj] = 0;
        pq.push({{0,  k},
                 {ni, nj}});
    }

    BFS();
}
728x90

'PS > C++' 카테고리의 다른 글

[백준/C++] 12015번 가장 긴 증가하는 부분 수열 2  (0) 2022.11.17
[백준/C++] 15927번 회문은 회문아니야!!  (0) 2022.11.15
[백준/C++] 11656번 접미사 배열  (0) 2022.11.14
[백준/C++] 17396번 백도어  (0) 2022.11.11
[백준/C++] 20040번 사이클 게임  (0) 2022.11.03
'PS/C++' 카테고리의 다른 글
  • [백준/C++] 12015번 가장 긴 증가하는 부분 수열 2
  • [백준/C++] 15927번 회문은 회문아니야!!
  • [백준/C++] 11656번 접미사 배열
  • [백준/C++] 17396번 백도어
yulee_to
yulee_to
  • yulee_to
    yulee
    yulee_to
  • 전체
    오늘
    어제
    • 전체 글 (123) N
      • CS (2)
        • OS (0)
        • DB (0)
        • Network (2)
      • Develop (21)
        • Spring (9)
        • Java (12)
        • Python (0)
        • Algorithm (0)
        • 기타 (0)
      • PS (39)
        • C++ (39)
        • Java (0)
      • TIL (16) N
      • Book (39)
        • 자바의 신 (32)
        • 스프링 입문을 위한 자바 객체 지향의 원리와 이해 (7)
      • ETC (4)
        • Blog (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    EC2
    boj
    Java
    에스넷시스템
    자바
    클라우드 활용 네트워크 엔지니어 부트캠프
    멀티캠퍼스it부트캠프
    부트캠프후기
    TiL
    스프링 입문
    스터디
    문제풀이
    자바의 신
    C++
    객체지향
    GodOfJava
    알고리즘
    에스넷시스템 부트캠프
    1일1백준
    백준
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
yulee_to
[백준/C++] 6087번 레이저 통신
상단으로

티스토리툴바