본문 바로가기

Coding Test

백준 21278 호석이 두 마리 치킨

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

#include <iostream>
#include <vector>

#define INF 987654321

using namespace std;


int dist[101][101];

int main() {

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int n, m;

    cin >> n >> m;

    for (int i = 1; i <= n; i++) {
        fill_n(&dist[i][0], n+1, INF);
    }


    for (int i = 0; i < m; i++) {
        int u, v;

        cin >> u >> v;


        dist[u][v] = 1;
        dist[v][u] = 1;
    }


    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }

    pair<int, int> ans;
    int distA = INF;


    for (int i = 1; i < n; i++) {
        for (int j = i + 1; j <= n; j++) {
            int temp = 0;
            for (int k = 1; k <= n; k++) {
                int tempI=0;
                int tempJ=0;
                if (i != k) {
                    tempI = dist[i][k];
                }
                if (j != k) {
                    tempJ = dist[j][k];
                }

                temp += min(tempI, tempJ);

            }
            if (distA > temp) {
                distA = temp;
                ans = make_pair(i, j);
            }
        }
    }

    cout << ans.first << " " << ans.second << " " << distA * 2;


    return 0;
}

1. 문제

n개의 건물과 m개의 도로가 있고, 각 도로에 대해 어떤 도시들끼리 연결되어 있는지 주어진다. 각 도로는 이동하는 데 편도 한 시간이 걸린다. 이 중 2개의 건물에 치킨집을 차리는데 다른 모든 건물에 대한 접근성(모든 건물에서 가장 가까운 치킨집까지 왕복하는 최단 시간의 총합)을 최소화하고자 한다. 이 때 치킨집으로 선정할 두 건물과 접근성을 구하여 출력하는 문제이다.

2. 풀이

100개의 건물 중 2개를 골라 나머지 건물에 대한 거리를 구하는 문제이다.

for (int i = 1; i <= n; i++) {
        fill_n(&dist[i][0], n+1, INF);
    }


    for (int i = 0; i < m; i++) {
        int u, v;

        cin >> u >> v;


        dist[u][v] = 1;
        dist[v][u] = 1;
    }

우선 거리 배열을 초기화한 후(dist[i][j]: i 건물로부터 j 건물까지 가는 데 걸리는 시간) 도로를 입력받아 갱신한다. 

    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }

모든 경우를 확인해야 하므로 all pair shortest path 문제이다. 플로이드 알고리즘으로 모든 거리를 구해준다.

    for (int i = 1; i < n; i++) {
        for (int j = i + 1; j <= n; j++) {
            int temp = 0;
            for (int k = 1; k <= n; k++) {
                int tempI=0;
                int tempJ=0;
                if (i != k) {
                    tempI = dist[i][k];
                }
                if (j != k) {
                    tempJ = dist[j][k];
                }

                temp += min(tempI, tempJ);

            }
            if (distA > temp) {
                distA = temp;
                ans = make_pair(i, j);
            }
        }
    }

i, j는 각각 치킨집 1과 치킨집 2의 번호이다. 건물 k에서 i, j로 각각 가는 데 걸리는 최소 시간을 구하여 더해준다. 그 후 정답 거리인 distA를 갱신한다.

    cout << ans.first << " " << ans.second << " " << distA * 2;

이 결과를 출력하면 답을 구할 수 있다. 접근성은 왕복으로 걸리는 시간을 계산하므로 2를 곱하여 출력한다.

'Coding Test' 카테고리의 다른 글

백준 2504 괄호의 값  (1) 2024.06.15
백준 10799 쇠막대기  (1) 2024.06.14
백준 1025 제곱수 찾기  (0) 2024.06.12
백준 15686 치킨 배달  (0) 2024.06.11
백준 1548 부분 삼각 수열  (0) 2024.06.10