※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 23255번 문제인 구름다리 2이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/23255
23255번: 구름다리 2
$1$번 건물부터 $N$번 건물까지 각 건물의 색을 공백으로 구분하여 한 줄에 출력한다.
www.acmicpc.net
문제에서 주어진 조건 중, 건물의 색을 1번부터 N번까지 순서대로 나열했을 때 사전순으로 가장 앞서게 건물 외벽을 색칠하라는 조건에 주목하자.
사전순으로 가장 앞서는 배열을 찾을 경우, 첫 건물서부터 현재 칠할 수 있는 최대한 앞순서에 오는 색을 골라나가는 방식으로 구해나가면 된다. 최대한 앞순서에 오는 색을 고르지 않는 순간이 있다면 그 순간의 색을 더 앞순서의 색을 칠하는 것으로 항상 사전순으로 앞서는 배열을 찾아낼 수 있기 때문이다.
한편, 구름다리의 개수가 10만개 이하이므로 색을 가장 많이 칠하더라도 500가지보다 많은 색을 칠할 경우는 발생하지 않는다는 점을 확인하자. 사전순으로 가장 앞서는 배열을 찾는 것이므로 굳이 큰 숫자에 대응되는 색을 사용할 이유가 없고, k번 색을 색칠해야만 하는 상황은 앞선 k-1가지의 색이 칠해져있는 각각의 건물과 다리가 놓여있어야만 하는 상황이라는 것을 확인하면 500개의 색을 칠할 상황이 오려면 다리가 몇 개 필요한지 계산해볼 수 있을 것이다.
이를 이용하여, 1번 건물서부터 건물을 하나씩 확인하며 지금까지 칠해지지 않은 가장 작은 숫자의 색을 건물에 칠해나가는 것으로 문제를 해결할 수 있다. 전체 구름다리의 개수가 10만개이므로 "건물 확인"의 횟수는 20만회 이하일 것이고 따라서 이러한 알고리즘으로 제한시간 내로 충분히 문제를 해결할 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
vector<int> G[100001];
int ans[100001];
int chk[500];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int N, M; cin >> N >> M;
while (M--) {
int x, y; cin >> x >> y;
G[x].emplace_back(y);
G[y].emplace_back(x);
}
for (int i = 1; i <= N; i++) {
memset(chk, 0, sizeof(chk));
for (auto node : G[i]) {
chk[ans[node]] = 1;
}
int idx = 1;
while (chk[idx]) idx++;
ans[i] = idx;
cout << idx << ' ';
}
}
'BOJ' 카테고리의 다른 글
[BOJ 23256 // C++] 성인 게임 (0) | 2022.01.28 |
---|---|
[BOJ 23974 // C++] 짝수 게임 (0) | 2022.01.27 |
[BOJ 23975 // C++] 정훈이는 민트초코맛 짜장라면이 먹고 싶다 (0) | 2022.01.25 |
[BOJ 7677 // C++] Fibonacci (0) | 2022.01.24 |
[BOJ 7490 // C++] 0 만들기 (0) | 2022.01.23 |