Algorithm/Baekjoon

[백준] 2645 : 회로배치

enopid 2025. 3. 26. 21:58

https://www.acmicpc.net/problem/2645

문제 분석

 정리하자면 격자 공간에서 각 격자마다 이동비용이 존재할 때 특정 두 지점을 잇는  최소 비용을 구하는 문제이다. 격자의 한변의 크기인 N이 50보다 작은 수이기 때문에 단순한 다익스트라로도 해결가능하다.

문제 해결 전략

 우선 각 격자마다 비용을 입력으로 들어오는 회로를 통해 구해내고 다익스트라를 수행한 뒤 간단한 경로 추적까지만 구현하면 된다.

코드

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <tuple>

using namespace std;

//문제분석
//격자에서 격자마다 비용이 존재할 때 특정 두 지점사이의 최소 비용 거리 구하기
//단순한 다익스트라문제
//  (V : N^2 = 2500, E=2*N*(N-1)=2N^2=5000, O(vlogE)=2500*12=3E4)
//각 격자를 노드로 엣지의 비용은 도착지의 비용
//=====================================================================
//해결전략
//1. N^2의 비용 맴 구하기
//2. 단순 다익스트라
//=====================================================================
//필요자료형
//변수
//vector<vector<int>> cost : 각 격자별 이동 cost
//vector<vector<int>> dist : 각 격자별 최소 비용
//priority_queue<int> : 다익스타룡 힙
//함수
//바로 구현

int N,K,M;
const int MAXV=150001; 

struct POINT
{
    POINT() : x(0), y(0) {};
    POINT(int _x, int _y) : x(_x), y(_y) {};
    bool IsVallid(){
        if (x>N || x<1 || y>N || y<1) return false;
        return true;
    }

    vector<POINT> GetAdjacentPoints(){
        vector<POINT> adjacentPoints;
        const static int d[4][2] ={
            {1,0},
            {-1,0},
            {0,1},
            {0,-1},
        };
        for (size_t i = 0; i < 4; i++) {
            POINT adjacentPoint = POINT(x+d[i][0],y+d[i][1]);
            if (adjacentPoint.IsVallid()) adjacentPoints.push_back(adjacentPoint);
        }
        return adjacentPoints;
    }

    friend ostream& operator<<(ostream& os, const POINT& pt){
        os << pt.x << " " << pt.y << " ";
        return os;
    }

    bool operator==(const POINT& otherPoint) {return (x==otherPoint.x)&&(y==otherPoint.y);}

    int x;
    int y;
};

int main()
{
    cin >> N;
    int x, y;
    cin >> x >> y;
    POINT P=POINT(x,y);
    cin >> x >> y;
    POINT Q=POINT(x,y);
    cin >> K >> M;
    vector<vector<int>> cost= vector<vector<int>>(N+1, vector<int>(N+1, 1));
    vector<vector<int>> dist= vector<vector<int>>(N+1, vector<int>(N+1, MAXV));

    auto cmp = [] (pair<int,POINT> a, pair<int,POINT> b)
    {
        return a.first > b.first;
    };

    priority_queue<pair<int,POINT>,vector<pair<int,POINT>>, decltype(cmp)> heapq(cmp);
    
    for (size_t i = 0; i < M; i++)
    {
        int circuitSize;
        cin >> circuitSize;
        int curx,cury,prevx,prevy;

        cin >> prevx >> prevy;
        for (size_t j = 0; j < circuitSize-1; j++)
        {
            cin >> curx >> cury;

            for (int x = prevx; x != curx; (curx>=prevx) ? x++ : x--) cost[x][prevy]=K;
            for (int y = prevy; y != cury; (cury>=prevy) ? y++ : y--) cost[prevx][y]=K;

            prevx=curx;
            prevy=cury;
        }
        cost[curx][cury]=K;
    }
    
    heapq.push(make_pair(cost[P.x][P.y],P));
    int curDist;
    POINT curPoint,nxtPoint;

    while(!heapq.empty()){
        tie(curDist,curPoint)=heapq.top();
        heapq.pop();

        if (dist[curPoint.x][curPoint.y]<=curDist) continue;
        dist[curPoint.x][curPoint.y]=curDist;
        if (curPoint==Q) break;

        for (const auto& nxtPoint : curPoint.GetAdjacentPoints())
        {
            int nxtDist=curDist+cost[nxtPoint.x][nxtPoint.y];
            if (dist[nxtPoint.x][nxtPoint.y]>nxtDist) heapq.push(make_pair(nxtDist,nxtPoint));
        }
    }

    vector<POINT> fullPath;
    fullPath.push_back(Q);
    curPoint=Q;
    while(!(curPoint==P)){
        for (auto nxtPoint : curPoint.GetAdjacentPoints())
        {
            if (dist[nxtPoint.x][nxtPoint.y]==dist[curPoint.x][curPoint.y]-cost[curPoint.x][curPoint.y]){
                curPoint=nxtPoint;
                fullPath.push_back(curPoint);
                break;
            }
        }
    }

    vector<POINT> turnPoints;
    turnPoints.push_back(P);
    for (int i = fullPath.size()-1; i >=0 ; i--)
        if (turnPoints.back().x!=fullPath[i].x && turnPoints.back().y!=fullPath[i].y) turnPoints.push_back(fullPath[i+1]);
    turnPoints.push_back(Q);
    
    cout << dist[Q.x][Q.y] << "\n";
    cout << turnPoints.size() << " ";
    for (auto pt : turnPoints) cout << pt;
}

 

'Algorithm > Baekjoon' 카테고리의 다른 글

[백준] 29820 : Love Letter  (0) 2025.03.31
[백준] 14380 : BFFS$($Large$)$  (1) 2025.03.27
[백준] 15328 : 산타의 선물  (0) 2025.03.22
[백준] 17234 : ScoringHack  (0) 2025.03.21
[백준] 18276 : Alergični Aron  (0) 2025.03.20