문제풀이/백준oj
[백준OJ] 1944번 복제 로봇
Hyeon-Uk
2021. 7. 18. 22:10
반응형
https://www.acmicpc.net/problem/1944
1944번: 복제 로봇
첫째 줄에 미로의 크기 N(4 ≤ N ≤ 50)과 열쇠의 개수 M(1 ≤ M ≤ 250) 이 공백을 사이에 두고 주어진다. 그리고 둘째 줄부터 N+1째 줄까지 미로의 정보가 주어진다. 미로는 1과 0, 그리고 S와 K로 주어
www.acmicpc.net
-풀이-
1. 먼저 BFS를 이용하여 각각의 키마다 시작점->각각의 키 까지의 최단거리(가중치)를 구해준 뒤, edge에 추가를 해준다. 만약 시작점->키까지 갈 수 없는 키가 있다면, -1을 출력해준다.
2. 각각의 키들끼리 BFS를 이용하여 최단거리(가중치)를 구해준 뒤, edge에 추가해준다.
3. 모든 edge들을 구해주었으면, 크루스칼 알고리즘을 이용하여 mst를 만들어주며, 모든 가중치들의 합을 구해준 뒤 출력한다.
-코드-
#include <iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int, int> pii;
char maze[50][50];
int parent[251];
bool visited[50][50] = { 0 };
int n, m;
vector<pair<pii, int>> edge;
vector<pii> keys;
int mv[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
pair<int, int> st;
bool compare(pair<pii, int> a, pair<pii, int> b) {
return a.second < b.second;
}
bool isIn(int i, int j) {
return 0 <= i && i < n && 0 <= j && j < n;
}
bool bfs(pii st,pii end,int v1,int v2) {
queue<pair<pair<int, int>, int>> q;
memset(visited, false, sizeof(visited));
q.push({ st,0 });
visited[st.first][st.second] = true;
while (!q.empty()) {
int x = q.front().first.first;
int y = q.front().first.second;
int t = q.front().second;
q.pop();
if (x == end.first&&y == end.second) {
edge.push_back({{v1,v2} ,t});
return true;
}
for (int i = 0; i < 4; i++) {
int nx = x + mv[i][0];
int ny = y + mv[i][1];
if (isIn(nx, ny) && !visited[nx][ny] && maze[nx][ny] != '1') {
q.push({ {nx,ny},t + 1 });
visited[nx][ny] = true;
}
}
}
return false;
}
void input() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> maze[i][j];
if (maze[i][j] == 'S') {
st = { i,j };
}
if (maze[i][j] == 'K') {
keys.push_back({ i,j });
}
}
}
}
int find(int a) {
if (a == parent[a]) {
return a;
}
else return find(parent[a]);
}
void union_parent(int a, int b) {
a = find(a);
b = find(b);
if (a < b) {
parent[b] = a;
}
else {
parent[a] = b;
}
}
int make_mst() {
int total_weight = 0;
for (int i = 0; i <= m; i++) {
parent[i] = i;
}
//가중치기준 오름차순 정렬
sort(edge.begin(), edge.end(), compare);
for (int i = 0; i < edge.size(); i++) {
int v1 = edge[i].first.first;
int v2 = edge[i].first.second;
int w = edge[i].second;
int pv1 = find(v1);
int pv2 = find(v2);
if (pv1 != pv2) {
union_parent(v1, v2);
total_weight += w;
}
}
return total_weight;
}
int solution() {
//정점->각 key들의 거리
for (int i = 0; i < keys.size(); i++) {
int kx = keys[i].first;
int ky = keys[i].second;
if (!bfs(st, { kx,ky },0,i+1)) {
return -1;
}
}
//키들간의 거리
for (int i = 0; i < keys.size(); i++) {
for (int j = i + 1; j < keys.size(); j++) {
int kx1 = keys[i].first;
int ky1 = keys[i].second;
int kx2 = keys[j].first;
int ky2 = keys[j].second;
bfs({ kx1,ky1 }, { kx2,ky2 }, i + 1, j + 1);
}
}
//mst구하기
return make_mst();
}
void solve() {
input();
cout << solution();
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
solve();
return 0;
}
반응형