Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- 후니의 쉽게 쓴 시스코 네트워킹
- 투 포인터
- 프로그래머스
- java
- 백트래킹
- mst
- 에라토스테네스의 체
- 문자열
- 위상정렬
- 유니온 파인드
- 스택
- Effective Java
- CS
- 백준
- BFS
- swea
- 구현
- 세그먼트 트리
- 시뮬레이션
- 완전탐색
- 플로이드-와샬
- 이분탐색
- 동적계획법
- JUnit 5
- dfs
- 알고리즘
- 그리디
- Kotlin
- 수학
- Network
Archives
반갑습니다!
[프로그래머스] 지형 이동 본문
풀이
해당 문제는 크게 3단계로 풀이된다.
- 사다리 설치가 필요없는 지형들 그룹화
- 그룹화된 지형들 사이를 이동하는 최소 비용 저장
- 저장된 최소 비용들로 MST 생성
1. 사다리 설치가 필요없는 지형들 그룹화
DFS 혹은 BFS를 사용하여 사다리가 필요없이 이동가능한 지형들을 하나의 그룹으로 표시한다. 아래의 코드에서는 방문 여부를 체크하는 visited
배열을 int
형으로 선언하여 방문 여부의 체크와 그룹 표시를 같이 진행하였다.
2. 그룹화된 지형들 사이를 이동하는 최소 비용 저장visited
배열에 그룹을 구분하였다면 각 그룹별 이동하는 최소 비용을 구하여 edges<pair<int, pair<int, int>>
에 저장한다.
3. 저장된 최소 비용들로 MST생성
MST는 Kruskal 알고리즘
을 사용하여 생성하여 답을 계산하였다.
코드
#include <string>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
using namespace std;
int n, h, num, ans = INT_MAX;
vector<int> parent, size;
vector<vector<int>> visited;
vector<bool> chk;
vector<pair<int, pair<int, int>>> edges;
const int dx[] = { -1, 0, 1, 0 }, dy[] = { 0, -1, 0, 1 };
int find(int u) {
if (u == parent[u]) return u;
return parent[u] = find(parent[u]);
}
void merge(int u, int v) {
u = find(u);
v = find(v);
if (u == v) return;
if (size[u] < size[v]) swap(u, v);
parent[v] = u;
if (size[u] == size[v]) size[u]++;
}
int kruskal() {
int cnt = 1;
int ret = 0;
// 최소 비용의 사다리부터 설치할 수 있도록 정렬
sort(edges.begin(), edges.end());
for (int i = 0; i < edges.size(); i++) {
int cost = edges[i].first;
int a = edges[i].second.first;
int b = edges[i].second.second;
if (find(a) == find(b)) continue;
merge(a, b);
ret += cost;
// 모든 그룹이 연결된 경우 반복문을 중지
if (++cnt == num) break;
}
return ret;
}
// 그룹 간 이동할 때 필요한 비용을 저장
void getCost(vector<vector<int>>& land) {
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= n || visited[y][x] == visited[ny][nx]) continue;
// 사다리를 설치해야하는 경우를 모두 저장
edges.push_back({ abs(land[y][x] - land[ny][nx]), {visited[y][x], visited[ny][nx]} });
}
}
}
}
// BFS를 해서 그룹을 분류
void bfs(int x, int y, int num, vector<vector<int>>& land) {
queue<pair<int, int>> q;
q.push({ x, y });
visited[y][x] = num;
while (!q.empty()) {
pair<int, int> cur = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
if (visited[ny][nx] || abs(land[cur.second][cur.first] - land[ny][nx]) > h) continue;
visited[ny][nx] = num;
q.push({ nx, ny });
}
}
}
int solution(vector<vector<int>> land, int height) {
int answer = 0;
n = land.size();
h = height;
// 그룹 분류
visited = vector<vector<int>>(n, vector<int>(n, 0));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (!visited[i][j]) bfs(j, i, ++num, land);
chk = vector<bool>(num, false);
parent = vector<int>(num + 1);
size = vector<int>(num + 1, 0);
// 사다리를 놓아야 하는 경우에 필요한 비용을 저장
getCost(land);
for (int i = 1; i <= num; i++) parent[i] = i;
// Kruskal 알고리즘을 통해 MST생성 및 결과 반환
answer = kruskal();
return answer;
}
'알고리즘 문제 풀이' 카테고리의 다른 글
[프로그래머스] 타일 장식물 (0) | 2020.04.06 |
---|---|
[프로그래머스] 하샤드 수 (0) | 2020.04.04 |
[프로그래머스] 예산 (0) | 2020.04.04 |
[프로그래머스] 문자열 내 마음대로 정렬하기 (0) | 2020.04.04 |
[프로그래머스] 정수 내림차순으로 배치하기 (0) | 2020.04.04 |