※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 25376번 문제인 이상한 스위치이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/25376
25376번: 이상한 스위치
1번 스위치가 2, 4, 5번 스위치에 영향을 주고, 4번 스위치가 5번 스위치에 영향을 준다. 1번 스위치를 직접 켤 때, 2, 4, 5번 스위치의 상태가 반전되면서, 1, 2, 4, 5번 스위치가 모두 켜진다. 이때, 4번
www.acmicpc.net
i번째 스위치가 켜져있으면 i번째 성분이 1, 꺼져있으면 i번째 성분이 0인 N-tuple들을 각각의 노드로 생각하고, 각 스위치의 상태에서 현재 누를 수 있는 스위치를 눌러 다른 상태로 바뀌는 것을 각 N-tuple을 잇는 에지로 생각하면 문제의 상황을 방향그래프로 모델링할 수 있다. 이 때, 문제에서 구하는 값은 초기상태를 나타내는 N-tuple이 나타내는 노드부터 모든 성분이 1인 N-tuple을 나타내는 노드까지의 최단거리와 같아진다. 이는 BFS를 이용해 구할 수 있다.
각 노드는 비트마스킹을 이용해 하나의 정수로 나타낼 수 있다. 즉, N-tuple의 i번째 성분을 정수의 i번째 비트로 대응시켜 표현하면 각 노드를 정수로 편하게 나타낼 수 있다. 각 스위치의 번호를 0-based로 나타내 문제를 해결해보자.
아래는 제출한 소스코드이다.
#include <iostream>
#include <queue>
using namespace std;
int N, S;
int dist[1048576];
int chng[20];
void bfs() {
queue<int> que;
que.push(S);
dist[S] = 1;
while (!que.empty()) {
int cur = que.front(); que.pop();
for (int i = 0; i < N; i++) {
if (cur & (1 << i)) continue;
int nxt = cur ^ chng[i];
if (dist[nxt]) continue;
dist[nxt] = dist[cur] + 1;
que.push(nxt);
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N;
for (int i = 0; i < N; i++) {
int x; cin >> x;
if (x) S |= (1 << i);
}
for (int i = 0; i < N; i++) {
chng[i] |= (1 << i);
int K; cin >> K;
while (K--) {
int x; cin >> x; x--;
chng[i] |= (1 << x);
}
}
bfs();
cout << dist[(1 << N) - 1] - 1;
}
'BOJ' 카테고리의 다른 글
[BOJ 3135 // C++] 라디오 (0) | 2023.01.24 |
---|---|
[BOJ 27260 // C++] Красивые перестановки (0) | 2023.01.24 |
[BOJ 25374 // C++] 등급 계산하기 (0) | 2023.01.23 |
[BOJ 27268 // C++] Рамки (0) | 2023.01.23 |
[BOJ 26432 // C++] Walktober (0) | 2023.01.23 |