백준 코딩
백준 2146번:다리 만들기
까르르꿍꿍
2021. 10. 9. 18:22
https://www.acmicpc.net/problem/2146
2146번: 다리 만들기
여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다
www.acmicpc.net
이 문제는 각 섬마다 그룹화가 필요하다. 그 이유는 최단 거리를 구하기 위해서 DFS를 이용해야 하는데 그냥 돌려버리면
최단거리가 아닌 각 섬에서 출발하여 중간에서 만나는 거리가 구해지기 때문이다. 즉 섬마다 그룹을 나눈다음에 각 섬끼리의 최단거리를 각각 구해야한다.
즉 이 문제는 DFS를 각 섬의 개수만큼 돌려서 최단거리를 구하면 된다.
#include<iostream>
#include <queue>
#include <cstdio>
using namespace std;
#pragma warning(disable : 4996)
int px[4] = { 0,0,1,-1 };
int py[4] = { 1,-1,0,0 };
int d[100][100]; //값 넣기
int sum[100][100]; //BFS를 진행할때 거리 계산할 용도
int grp[100][100]; //그룹화를 할 배열
int cnt = 1; //섬의 그룹번호 지정을 위한 변수
int m;
void dfs(int x, int y) { //섬의 그룹화를 위한 dfs
grp[x][y] = cnt;
for (int k = 0; k < 4; k++) {
int nx = x + px[k];
int ny = y + py[k];
if (0 <= nx && nx < m && 0 <= ny && ny < m) {
if (grp[nx][ny] == 0 && d[nx][ny] == 1) {
dfs(nx, ny);
}
}
}
}
int main() {
cin >> m;
for (int i = 0; i < m; i++) {
for (int k = 0; k < m; k++) {
scanf("%1d", &d[i][k]);
}
}
for (int i = 0; i < m; i++) { //그룹번호 지정
for (int k = 0; k < m; k++) {
if (grp[i][k] == 0 && d[i][k] == 1) {
dfs(i, k);
cnt++;
}
}
}
int ans = -1;
for (int l = 1; l < cnt; l++) {
queue<pair<int, int>> q;
for (int i = 0; i < m; i++) {
for (int k = 0; k < m; k++) {
sum[i][k] = -1; //섬이 아니면 -1대입
if (grp[i][k] == l) {
sum[i][k] = 0; //섬이면 0대입
q.push(make_pair(i, k));
}
}
}
while (!q.empty()) {
int x = q.front().first;
int y = q.front().second;
q.pop();
for (int i = 0; i < 4; i++) {
int nx = x + px[i];
int ny = y + py[i];
if (0 <= nx && nx < m && 0 <= ny && ny < m) { //한개의 섬을 기준으로 모든 거리 값 구하기
if (sum[nx][ny] == -1) {
sum[nx][ny] = sum[x][y] + 1;
q.push(make_pair(nx, ny));
}
}
}
}
for (int i = 0; i < m; i++) {
for (int k = 0; k < m; k++) {
if (d[i][k] == 1 && grp[i][k] != l) { //섬이면서 다른 섬인경우
if ((ans == -1) || (sum[i][k] - 1 < ans)) { //최단거리 구하기
ans = sum[i][k] - 1;
}
}
}
}
}
cout << ans;
return 0;
}