※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 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;
}
728x90

'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

+ Recent posts