728x90
https://www.acmicpc.net/problem/17472
삼성 A형 기출 문제로 좋은 문제다. 이전에 삼성 대학생 역량 어쩌구를 할 때도 이런 종류의 문제가 많았다. bfs, dfs 후 경로를 사용해 다익스트라를 사용한다는 문제가 있었다. 하지만 이 문제는 mst를 하는 문제이다.
1. bfs or dfs를 통해 각 섬의 번호를 매긴다. (그래프 탐색)
2. 그리고 다시한 번 bfs를 통해 각 섬끼리의 최소 거리를 구해 그래프를 구성한다. (bfs, 구현 능력)
3. 구성한 그래프를 통해 MST를 진행한다. (MST 프림 or 크루스칼)
그래프의 크기가 크지 않아서 시간을 생각하는 것 보다 코드를 어떻게 해야 간단하고 완벽하게 구성할 수 있을까 고민하는 것이 관건이이며, BFS, MST 같은 기본 알고리즘 구현을 할 수 있어야하는 좋은 문제였다.
나도 오랜만에 MST를 구현하려니 기억이 안나서 예전 코드를 들여다봤다 ㅠ
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int maps[101][101];
int N, M;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int num = 1;
int answer = 0;
queue<pair<int, int>> q;
bool visited[101][101] = {false,};
bool Range(int x, int y){
return x > -1 && x < N && y > -1 && y < M;
}
void bfs(int k){
while(!q.empty()){
int r = q.front().first;
int c = q.front().second;
q.pop();
maps[r][c] = k;
for(int i = 0; i < 4; i++){
int nextx = r + dx[i];
int nexty = c + dy[i];
if(Range(nextx, nexty) && !visited[nextx][nexty] && maps[nextx][nexty] == 1){
visited[nextx][nexty] = true;
maps[nextx][nexty] = k;
q.push({nextx, nexty});
}
}
}
}
int board[11][11];
void setting(int r, int c){
memset(visited, false, sizeof visited);
queue<pair<int, int>> q;
q.push({r, c});
visited[r][c] = true;
while(!q.empty()){
int x = q.front().first;
int y = q.front().second;
q.pop();
//cout << maps[x][y] << " ";
for(int i = 0; i < 4; i++){
int nextx = x;
int nexty = y;
int dist = 0;
while(true){
dist++;
nextx += dx[i];
nexty += dy[i];
if(!Range(nextx, nexty) || maps[nextx][nexty] == maps[x][y])
break;
else if(maps[nextx][nexty] > 0 && maps[nextx][nexty] != maps[x][y]){
if(dist - 1 < 2) break;
int a = maps[x][y];
int b = maps[nextx][nexty];
board[a][b] = min(board[a][b], dist - 1);
board[b][a] = board[a][b];
break;
}
}
}
for(int i = 0; i < 4; i++){
int nextx = x + dx[i];
int nexty = y + dy[i];
if(Range(nextx, nexty) && !visited[nextx][nexty] && maps[x][y] == maps[nextx][nexty]){
visited[nextx][nexty] = true;
q.push({nextx, nexty});
}
}
}
}
vector<pair<int, int>> vertex[11];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> PQ;
void setgraph() {
for (int i = 1; i <= num - 1 ; i++) {
for(int j = 1; j <= num - 1; j++){
vertex[i].push_back({j, board[i][j]});
vertex[j].push_back({i, board[i][j]});
}
}
PQ.push({0, 1});
}
void PRIM() {
bool mstVis[11] = {false};
while (!PQ.empty()) {
int here = PQ.top().second;
int heredis = PQ.top().first;
PQ.pop();
if (mstVis[here] == true) continue;
else mstVis[here] = true;
answer += heredis;
for (int i = 0; i < vertex[here].size(); i++) {
int next = vertex[here][i].first;
int nextdis = vertex[here][i].second;
PQ.push(make_pair(nextdis, next));
}
}
}
int main(){
cin >> N >> M;
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
cin >> maps[i][j];
}
}
int sx, sy;
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
if(visited[i][j] == false && maps[i][j] == 1){
q.push({i, j});
bfs(num);
num++;
sx = i;
sy = j;
}
}
}
for(int i = 0; i <= num; i++){
for(int j = 0; j <= num; j++){
board[i][j] = 100000;
}
}
bool check[10] = {false};
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
if(maps[i][j] > 0 && check[maps[i][j]] == false){
check[maps[i][j]] = true;
setting(i, j);
}
}
}
// for(int i = 0; i < N; i++){
// for(int j = 0; j < M; j++){
// cout << maps[i][j] << " ";
// }
// cout << endl;
// }
// for(int i = 1; i <= num - 1; i++){
// for(int j = 1; j <= num - 1; j++){
// if(board[i][j] == 100000) cout << "IN ";
// else cout << board[i][j] << " ";
// }
// cout << endl;
// }
setgraph();
PRIM();
if(answer >= 100000) cout << -1 << '\n';
else cout << answer << '\n';
}
'백준 문제 풀이' 카테고리의 다른 글
백준 1010번 - 다리놓기 (C++) (1) | 2024.06.03 |
---|---|
백준 1700번 - 멀티탭 스케줄링 (0) | 2024.06.03 |
백준 17143번 - 낚시왕(C++) (0) | 2024.06.01 |
백준 13460번 - 구슬 탈출2 (0) | 2024.05.28 |
백준 2458번 키 순서 (Java) (0) | 2024.05.01 |