일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- DP문제
- 코테 문제
- tflite
- 딥러닝
- MCU 딥러닝
- 영상처리
- dfs
- 삼성역테
- 알고리즘
- 포스코 AI교육
- sort
- 다이나믹프로그래밍
- 삼성역량테스트
- 임베디드 딥러닝
- 삼성코테
- 자료구조
- 그리디
- 포스코 교육
- tinyml
- 초소형머신러닝
- dfs문제
- 코딩테스트
- bfs문제
- 삼성코딩테스트
- 포스코 ai 교육
- BFS
- TensorFlow Lite
- 컴퓨팅사고
- 코테
- DP
- Today
- Total
코딩뚠뚠
[백준문제풀이] 2146 다리 만들기 본문
풀이일시 : 2020-11-05
문제 :
여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다는 생각을 하게 되었다. 그래서 그는, 생색내는 식으로 한 섬과 다른 섬을 잇는 다리 하나만을 만들기로 하였고, 그 또한 다리를 가장 짧게 하여 돈을 아끼려 하였다.
이 나라는 N×N크기의 이차원 평면상에 존재한다. 이 나라는 여러 섬으로 이루어져 있으며, 섬이란 동서남북으로 육지가 붙어있는 덩어리를 말한다. 다음은 세 개의 섬으로 이루어진 나라의 지도이다.
위의 그림에서 색이 있는 부분이 육지이고, 색이 없는 부분이 바다이다. 이 바다에 가장 짧은 다리를 놓아 두 대륙을 연결하고자 한다. 가장 짧은 다리란, 다리가 격자에서 차지하는 칸의 수가 가장 작은 다리를 말한다. 다음 그림에서 두 대륙을 연결하는 다리를 볼 수 있다.
물론 위의 방법 외에도 다리를 놓는 방법이 여러 가지 있으나, 위의 경우가 놓는 다리의 길이가 3으로 가장 짧다(물론 길이가 3인 다른 다리를 놓을 수 있는 방법도 몇 가지 있다).
지도가 주어질 때, 가장 짧은 다리 하나를 놓아 두 대륙을 연결하는 방법을 찾으시오.
입력 :
첫 줄에는 지도의 크기 N(100이하의 자연수)가 주어진다. 그 다음 N줄에는 N개의 숫자가 빈칸을 사이에 두고 주어지며, 0은 바다, 1은 육지를 나타낸다. 항상 두 개 이상의 섬이 있는 데이터만 입력으로 주어진다.
ex)
10
1 1 1 0 0 0 0 1 1 1
1 1 1 1 0 0 0 0 1 1
1 0 1 1 0 0 0 0 1 1
0 0 1 1 1 0 0 0 0 1
0 0 0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
출력 :
첫째 줄에 가장 짧은 다리의 길이를 출력한다.
ex)
3
풀이 :
우선 육지의 개념 즉 이어져있다는 개념이 무엇인지 살펴보면 동,서,남,북으로 이어져 있어야 한다고 한다. 그러므로 대각선으로 이어져 있는 것은 이어져있는것이 아니다.
각 육지를 바다쪽으로 간척해나가며 문제를 풀어보자.
-> DFS로 각 섬마다 번호를 마킹해주도록 하자
-> BFS로 섬의 부피를 1씩 늘이고, 닿는다면 그때의 수를 센다.
( bfs로 섬의 부피를 늘릴때 1,2,3 섬을 모두 같이 늘리면 닿는 것을 판별하기 애매할 수 있다. 따라서 DFS로 설정해 준 섬의 번호를 돌아가며 1,2,3섬을 차례로 bfs 해준다. 그리고 그들의 min을 result로 삼는다.)
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
#define MAX 100
using namespace std;
int graph[MAX][MAX];
int dx[] = { 0,0,1,-1 }; //상하좌우 탐색위해
int dy[] = { 1,-1,0,0 };
int visited[MAX][MAX];
int N;
int a;
int bfs(int cnt) { //bfs 돌린다
queue <pair<int,int>> q;
//전체를 돌며 cnt 섬만 q에 넣을거다.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (graph[i][j] == cnt) { //한 섬의 번호
visited[i][j] = true; //방문 true
q.push({ i,j }); //큐에 넣기
}
}
}
int result = 0;
while (!q.empty()) { //큐가 빌때까지 반복한다.
int size = q.size(); //q의 사이즈 즉 초기에는 섬의 크기
for (int i = 0; i < size; i++) { //사이즈만큼 반복. 전체의 부피를 4방향으로 늘릴것
//이게 size만큼 반복되면 한 겹(result)이 쌓인 것 그다음 q는 그 쌓인 부피를 또 늘릴것이다.
int y = q.front().first;
int x = q.front().second;
q.pop(); //pop해준다.
for (int i = 0; i < 4; i++) { //4방향 탐색하기
int ny = y + dy[i];
int nx = x + dx[i];
if (0 <= ny && ny < N && 0 <= nx && nx < N) { //범위 조건을 만족하고
if (graph[ny][nx] && graph[ny][nx] != cnt) { //다른섬과 맞닿으면
return result; //result를 return한다.
}
else if (!graph[ny][nx] && !visited[ny][nx]) //graph가 0이고(섬이아니고) visited하지 않았다면
{
visited[ny][nx] = true; //방문해주고
q.push({ ny,nx }); //push 해준다.
}
}
}
}
result++;
}
}
void dfs(int y, int x, int cnt) { //dfs를 통해 각 섬의 번호를 만들어준다.
visited[y][x] = true; //지금 들어온 번호 true로 만들어주고 시작
graph[y][x] = cnt; //섬의 번호를 cnt로 만들어준다.
for (int i = 0; i < 4; i++) { // 4번반복
int ny = y + dy[i]; //번호매겨준다.
int nx = x + dx[i];
if (0 <= ny && ny < N && 0 <= nx && nx < N) { //범위를 충족하면
if (graph[ny][nx] && !visited[ny][nx]) { //땅이면(0이 아니여야됨) && 방문하지않았다면
dfs(ny, nx, cnt); //다시 dfs 넣어서 점령한다.
}
}
}
}
int main() {
cin >> N;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> a;
graph[i][j] = a;
}
}
//각 섬을 다른수로 마킹해주기 위한 dfs
int cnt = 1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (graph[i][j] && !visited[i][j])
dfs(i, j, cnt++); //다끝나고 나오면 또 cnt증가시켜서 다른곳들어감
}
}
int result = 100000;
//result min의 의미 : 한 번 bfs를 실행하면 1 섬에서 2, 3 섬으로 가는 다리 중 최소를 얻음
// 2 섬에서의 1 3 까지의 result와 3 섬에서 2 1 까지의 최소랑 비교하여 min을 찾기위함
for (int i = 1; i < cnt; i++) {
memset(visited, 0, sizeof(visited));
result = min(result, bfs(i));
}
cout << result << endl;
return 0;
}
참고자료 : BFS
참고자료 : DFS
참고자료 : memset 함수
'알고리즘 문제풀이 > 백준문제풀이' 카테고리의 다른 글
[백준문제풀이] 1525 퍼즐 (0) | 2021.01.02 |
---|---|
[백준문제풀이] 9019 DSLR (0) | 2021.01.02 |
[백준문제풀이] 1963 소수 경로 (0) | 2021.01.02 |
[백준문제풀이] 1697 숨바꼭질 (0) | 2021.01.02 |
[백준문제풀이] 1966 프린터 큐 (0) | 2021.01.02 |