가취공부하자

[백준] 2146 다리만들기 c++ 본문

알고리즘/백준

[백준] 2146 다리만들기 c++

keepGGoing 2021. 4. 1. 12:14

문제

www.acmicpc.net/problem/2146

 

2146번: 다리 만들기

여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다

www.acmicpc.net

 

문제풀이

1. 섬끼리 분류하기 위해서 각 섬에게 id를 할당한다.

 

2. A섬에서 B섬까지의 거리를 구한다.

 

 

<섬끼리 분류하기 위해서 섬에게 id를 할당하는 코드>

 

void bfs_ground(int a, int b, int id) {
	queue<pair<int, int> >q;
	int x, y, next_x, next_y;
	x = a, y = b;
	q.push({ a,b });
	visit[x][y] = true;
	while (!q.empty()) {
		x = q.front().first;
		y = q.front().second;
		map[x][y] = id;
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			next_x = x + dx[i];
			next_y = y + dy[i];

			if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < n && !visit[next_x][next_y]) {
				if (map[next_x][next_y] == 1) {
					visit[next_x][next_y] = true;
					q.push({ next_x,next_y });
				}
			}
		}
	}
}

 

<A섬에서 B섬까지의 거리를 구한다.>

 

int bfs_bridge(int id) {
	queue<pair<int, int> >q;
	int distance = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (map[i][j] == id) {
				q.push({ i,j });
				visit[i][j] = true;
			}
		}
	}
	int x, y, next_x, next_y, queue_size;
	while (!q.empty()) {
		queue_size = q.size();
//queue_size를 먼저 구하면 distance를 간다한게 구할수 있다
//for문이 다 돌았다 ==> 각 위치에서 1만큼씩 이동
		for (int i = 0; i < queue_size; i++)
		{
			x = q.front().first;
			y = q.front().second;
			q.pop();

			for (int j = 0; j < 4; j++)
			{
				next_x = x + dx[j];
				next_y = y + dy[j];
				
				if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < n && !visit[next_x][next_y]) {
					
					if (map[next_x][next_y] == 0) {
						q.push({ next_x,next_y });
						visit[next_x][next_y] = true;
					}
					else if (map[next_x][next_y] != id)
						return distance;
				}
			}
		}
		distance++;
	}
	return 0;
}

 

완성된 코드

 

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

using namespace std;

int map[101][101];
bool visit[101][101];
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
int n;

void bfs_ground(int a, int b, int id) {
	queue<pair<int, int> >q;
	int x, y, next_x, next_y;
	x = a, y = b;
	q.push({ a,b });
	visit[x][y] = true;
	while (!q.empty()) {
		x = q.front().first;
		y = q.front().second;
		map[x][y] = id;
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			next_x = x + dx[i];
			next_y = y + dy[i];

			if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < n && !visit[next_x][next_y]) {
				if (map[next_x][next_y] == 1) {
					visit[next_x][next_y] = true;
					q.push({ next_x,next_y });
				}
			}
		}
	}
}

int bfs_bridge(int id) {
	queue<pair<int, int> >q;
	int distance = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (map[i][j] == id) {
				q.push({ i,j });
				visit[i][j] = true;
			}
		}
	}
	int x, y, next_x, next_y, queue_size;
	while (!q.empty()) {
		queue_size = q.size();
		//distance를 쉽게 계산하기 위해서 하나씩
		for (int i = 0; i < queue_size; i++)
		{
			x = q.front().first;
			y = q.front().second;
			q.pop();

			for (int j = 0; j < 4; j++)
			{
				next_x = x + dx[j];
				next_y = y + dy[j];
				
				if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < n && !visit[next_x][next_y]) {
					
					if (map[next_x][next_y] == 0) {
						q.push({ next_x,next_y });
						visit[next_x][next_y] = true;
					}
					else if (map[next_x][next_y] != id)
						return distance;
				}
			}
		}
		distance++;
	}
	return 0;
}




int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cin >> map[i][j];
		}
	}
	memset(visit, false, sizeof(visit));	
	int id = 1;
	//대륙별로 id부여하기
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (map[i][j] == 1&&!visit[i][j]) {
				bfs_ground(i, j, id++);
			}
		}
	}

	//대륙사이 가장 짧은 거리 구하기
	int result = 100000;
	for (int i = 1; i < id; i++)
	{
		memset(visit, false, sizeof(visit));
		result = min(result, bfs_bridge(i));
	}

	cout << result;

	return 0;
}

 

 

참고

ssungkang.tistory.com/entry/C-BAEKJOON-2146-%EB%8B%A4%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준]12865 평범한 배낭 c++  (0) 2021.06.21
[백준] 1300 K번째 수 c++  (0) 2021.04.07
[백준] 10775 공항 c++  (0) 2021.03.31
[백준] 2644 촌수계산 c++  (0) 2021.03.31
[백준] 11602 카드게임 c++  (0) 2021.03.31