백준 2146 다리 만들기

2020. 9. 10. 01:06·알고리즘/BOJ

www.acmicpc.net/problem/2146

 

2146번: 다리 만들기

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

www.acmicpc.net

처음엔 완전 탐색으로 다리를 전부 놓으면서 최적의 수를 찾는 줄 알았다.

알고리즘 분류를 보니 BFS, DFS여서 어떻게 해야 할지 감이 잘 안 잡혔다.

 

1. 1차 BFS를 통해 대륙의 번호를 지정해준다.

2. 큐에 땅의 위치를 전부 삽입해준다

3. BFS를 한번 더 돌려서 이동 범위가 바다라면 큐에 삽입해준다

4. 이동 범위가 땅인데 대륙 번호가 같지 않다면 거기까지의 거리를 리턴해준다.

 

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

#define fast ios::sync_with_stdio(false); cin.tie(0);
#define X first
#define Y second
#define f(i,n) for(int i=0;i<n;i++)

int n, ar[101][101];
bool vis[101][101];
int dx[4] = { 1,-1,0,0 };
int dy[4] = { 0,0,1,-1 };
vector<pair<int, int>> V;

void init() {
	f(i, 101) fill(vis[i], vis[i] + 101, false);
}

void numbering(int x, int y, int num) {
	queue<pair<int, int>> Q;
	Q.push({ x,y }); vis[x][y] = true;
	ar[x][y] = num;
	while (!Q.empty()) {
		auto cur = Q.front(); Q.pop();
		f(i, 4) {
			int nx = cur.X + dx[i];
			int ny = cur.Y + dy[i];
			if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
			if (!vis[nx][ny] && ar[nx][ny] == -1) {
				Q.push({ nx,ny }); vis[nx][ny] = true; ar[nx][ny] = num;
			}
		}
	}
}

int bfs(int num) {

	//다리 놓는 BFS 하기전 땅을 전부 큐에 넣어주고 그 땅에서 바다라면 큐에 삽입
	//땅인데 같은 넘버가 아니라면 종료해준다.

	queue<pair<int, int>> Q;
	f(i, n) {
		f(j, n) {
			if (ar[i][j] == num) {
				Q.push({ i,j }); vis[i][j] = true;
			}
		}
	}

	int ret = 0;
	while (!Q.empty()) {
		int len = Q.size(); //큐 사이즈만큼 돌려야 런타임 에러를 피할듯
		f(i, len) {
			auto cur = Q.front(); Q.pop();
			f(dir, 4) {
				int nx = cur.X + dx[dir];
				int ny = cur.Y + dy[dir];
				if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
				if (ar[nx][ny] != 0 && ar[nx][ny] != num) return ret;
				else if (ar[nx][ny] == 0 && !vis[nx][ny]) {
					//cout << "Check" << '\n';
					vis[nx][ny] = true; Q.push({ nx,ny });
				}
			}
		}
		ret++;
		//cout << "RET= " << ret << '\n';
	}
}

int main() {
	fast;

	cin >> n;
	f(i, n) {
		f(j, n) {
			cin >> ar[i][j];
			if (ar[i][j] == 1) {
				ar[i][j] = -1;
				V.push_back({ i,j });
			}
		}
	}
	int num = 1;
	for (int i = 0; i < (int)V.size(); i++) {
		auto cur = V[i];
		if (!vis[cur.X][cur.Y]) {
			numbering(cur.X, cur.Y, num); num++;
		}
	}

	////To Numbering Check
	//cout << endl;
	//f(i, n) { f(j, n) { cout << ar[i][j] << ' '; }cout << '\n'; }

	int ans = 1e9;
	for (int i = 1; i < num; i++) {
		init();
		//cout << "ans = " << ans << '\n';
		ans = min(ans, bfs(i));
	}
	cout << ans << endl;

	return 0;
}

 

이런 그래프 문제는 경우의 수마다 맵을 출력 해보며 오차범위를 찾는 게 가장 좋은 것 같다.

이번에도 nx를 ny로 써서 몇 번은 틀렸다 ㅜ.

 

 

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

백준 1991 트리 순회  (0) 2020.09.10
백준 19699 소-난다!  (0) 2020.09.10
백준 9466 텀 프로젝트  (0) 2020.09.09
백준 4963 섬의 개수  (0) 2020.09.09
백준 2331 반복수열  (0) 2020.09.08
'알고리즘/BOJ' 카테고리의 다른 글
  • 백준 1991 트리 순회
  • 백준 19699 소-난다!
  • 백준 9466 텀 프로젝트
  • 백준 4963 섬의 개수
khyu2
khyu2
  • khyu2
    dev log
    khyu2
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 알고리즘
        • BOJ
        • Programmers
        • Algorithm
        • SWEA
      • 개발
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    이분 탐색
    이분탐색
    피사노 주기
    알고리즘
    구현
    프로그래머스
    시뮬레이션
    트리
    코딩테스트 연습
    BFS
    분할 정복
    다익스트라
    냅색
    큐
    완전 탐색
    dp
    GREEDY
    BOJ
    팰린드롬
    피보나치 수
    유니온 파인드
    크루스칼
    조합
    완전탐색
    MST
    우선순위 큐
    dfs
    SWEA
    행렬 제곱
    소수
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
khyu2
백준 2146 다리 만들기
상단으로

티스토리툴바