문제 링크 : https://www.acmicpc.net/problem/2146
2146번: 다리 만들기
여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다는 생각을 하게 되었다. 그래서 그는, 생색내는 식으로 한 섬과 다른 섬을 잇는 다리 하나만을 만들기로 하였고, 그 또한 다리를 가장 짧게 하여 돈을 아끼려 하였다. 이 나라는 N×N크기의 이차원 평면상에 존재한다. 이 나라는 여러 섬으로 이루어져 있으며, 섬이란 동서남북
www.acmicpc.net
문제 설명
1. N x N 행렬에 0과 1로 이루어진 배열이 주어짐.
2. 1은 육지를 의미하고 0은 바다를 의미.
3. 육지에서 다른 육지로 가기위한 다리를 만들때 두개의 육지가 이어지는 최소의 다리 길이를 return.
알고리즘
1. 육지 마다 번호를 붙여준다. (dfs 이용)
2. BFS 알고리즘을 이용하여 육지를 한칸씩 확장한다.
3.육지를 확장하다가 다른 육지를 만났을때 길이를 return 하고 그중 최소값을 출력한다.
코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #include<iostream> #include<algorithm> #include<queue> using namespace std; int map[101][101], N, num_map[101][101], visited[101][101]; int dx[] = { 1,-1,0,0 }; int dy[] = { 0,0,1,-1 }; void dfs(int y, int x, int num) {//섬에 숫자 붙이는 코드. if (visited[y][x]) return; visited[y][x] = 1; num_map[y][x] = num; for (int i = 0; i < 4; i++) { int next_y = y + dy[i]; int next_x = x + dx[i]; if (next_y >= 0 && next_y < N && next_x >= 0 && next_x < N) { if (map[next_y][next_x] && !visited[next_y][next_x]) { dfs(next_y, next_x, num); } } } } int dfsAll() {//섬에 숫자 붙이기 int cnt = 1; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (!visited[i][j] && map[i][j]) { dfs(i, j, cnt); cnt++; } } } return cnt; } void reset() { //방문 초기화 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { visited[i][j] = 0; } } } int bfs(int num) { //육지확장 int result = 0; queue<pair<int, int>> q; //num_map 에서 num인거 다 큐에 push; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (num_map[i][j] == num)q.push(make_pair(i, j)); } } while (!q.empty()) { int Size = q.size(); for (int i = 0; i < Size; i++) { pair<int, int> p = q.front(); visited[p.first][p.second] = 1; q.pop(); for (int j = 0; j < 4; j++) { int next_y = p.first + dy[j]; int next_x = p.second + dx[j]; if (next_y >= 0 && next_y < N && next_x >= 0 && next_x < N) { if (!num_map[next_y][next_x] && !visited[next_y][next_x]) { q.push(make_pair(next_y, next_x)); visited[next_y][next_x] = 1; } else if (num_map[next_y][next_x] &&num_map[next_y][next_x] != num) { return result; } } } } result++; } } int main() { cin.tie(NULL); ios::sync_with_stdio(false); cin >> N; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { cin >> map[i][j]; } } int num = dfsAll(); int ans = 1000000; for (int i = 1; i < num; i++) { reset(); ans = min(bfs(i), ans); } cout << ans; } | cs |
'c++ > 백준' 카테고리의 다른 글
백준 1010번 : 다리 놓기 (0) | 2020.04.26 |
---|---|
백준 1520번: 내리막길 (0) | 2020.04.26 |
백준 10986 번 : 나머지 합 (0) | 2020.04.20 |
백준 17136번 : 색종이 붙이기 (0) | 2020.04.20 |
백준 11660번 : 구간 합 구하기 5 (0) | 2020.04.20 |