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

 

이번에 볼 문제는 백준 20942번 문제인 신촌지역 초중고등학생 프로그래밍 대회 동아리 연합 대회이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/20942 

 

20942번: 신촌지역 초중고등학생 프로그래밍 대회 동아리 연합 대회

첫 번째 자리에는 $15$세의 참가자가 이미 배치되어 있다. 두 번째, 세 번째, 네 번째 자리에 각각 $17$세, $12$세, $19$세의 참가자를 배치하면, $15 \operatorname{\&} 17 = 1$, $15 \operatorname{\&} 12 = 12$, $12 

www.acmicpc.net

각 참가자의 나이를 이진수로 표현하면 1의자리, 2의자리, 4의자리, 8의자리, 16의자리의 다섯개의 비트로 표현이 가능하다. 각 나이의 비트가 0인지 1인지를 TF로 생각하고, 문제에서 주어진 조건들을 적절히 명제로 바꿔 주어진 문제를 2-SAT 문제로 모델링할 수 있다.

 

먼저 각 나이는 8 이상 19 이하이므로, 16의 자리 비트가 0이라면 8의 자리 비트가 1이어야하고, 1이라면 8의 자리와 4의 자리 비트가 0이 되어야 한다. 위의 조건만 만족한다면 다섯 개의 비트가 나타내는 수는 항상 8 이상 19 이하가 된다.

 

두 정수를 and 또는 or연산을 했을 때 나오는 수에 대한 명제 또한 비트별로 떼어 5개의 명제로 구분할 수 있다.

 

아래는 제출한 소스코드이다.

#define NODE 500001
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int N, gap; // 2-SAT 정점개수(TF분할 말고), T와F노드 사이 값의 차이
vector<int> G[NODE];
int dfi[NODE]; int dfidx = 1;
int sci[NODE]; int scidx = 1;
vector<int> stk;
int twosatdfs(int current) {
	stk.emplace_back(current);
	int ret = dfi[current] = dfidx++;
	for (auto node : G[current]) {
		if (sci[node]) continue;
		if (dfi[node]) ret = min(ret, dfi[node]);
		else ret = min(ret, twosatdfs(node));
	}

	if (ret == dfi[current]) {
		while (stk.back() != current) {
			sci[stk.back()] = scidx;
			stk.pop_back();
		}
		sci[stk.back()] = scidx++;
		stk.pop_back();
	}

	return ret;
}

bool ans[NODE];
bool TWOSAT() {
	for (int i = 1; i <= N; i++) {
		if (sci[i]) continue;
		twosatdfs(i);
	}
	for (int i = 1 + gap; i <= N + gap; i++) {
		if (sci[i]) continue;
		twosatdfs(i);
	}
	
	for (int i = 1; i <= N; i++) {
		if (sci[i] < sci[i + gap]) ans[i] = 1;
		else if (sci[i] > sci[i + gap]) ans[i] = 0;
		else return 0;
	}
	return 1;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N; N *= 5;
	gap = 250000;
	for (int i = 1; i < N; i += 5) {
		G[i + 4].emplace_back(gap + i + 3);
		G[i + 3].emplace_back(gap + i + 4);
		G[i + 4].emplace_back(gap + i + 2);
		G[i + 2].emplace_back(gap + i + 4);
		G[gap + i + 4].emplace_back(i + 3);
		G[gap + i + 3].emplace_back(i + 4);

		int x; cin >> x;
		if (x == 0) continue;
		if (x & 1) G[gap + i].emplace_back(i);
		else G[i].emplace_back(gap + i);
		if (x & 2) G[gap + i + 1].emplace_back(i + 1);
		else G[i + 1].emplace_back(gap + i + 1);
		if (x & 4) G[gap + i + 2].emplace_back(i + 2);
		else G[i + 2].emplace_back(gap + i + 2);
		if (x & 8) G[gap + i + 3].emplace_back(i + 3);
		else G[i + 3].emplace_back(gap + i + 3);
		if (x & 16) G[gap + i + 4].emplace_back(i + 4);
		else G[i + 4].emplace_back(gap + i + 4);
	}

	int M; cin >> M;
	while (M--) {
		char c; int x, y, z; cin >> c >> x >> y >> z;
		int xi = (x - 1) * 5 + 1, yi = (y - 1) * 5 + 1;
		if (c == '&') {
			if (z & 1) {
				G[gap + xi].emplace_back(xi);
				G[gap + yi].emplace_back(yi);
			}
			else {
				G[xi].emplace_back(yi + gap);
				G[yi].emplace_back(xi + gap);
			}
			if (z & 2) {
				G[gap + xi + 1].emplace_back(xi + 1);
				G[gap + yi + 1].emplace_back(yi + 1);
			}
			else {
				G[xi + 1].emplace_back(yi + gap + 1);
				G[yi + 1].emplace_back(xi + gap + 1);
			}
			if (z & 4) {
				G[gap + xi + 2].emplace_back(xi + 2);
				G[gap + yi + 2].emplace_back(yi + 2);
			}
			else {
				G[xi + 2].emplace_back(yi + gap + 2);
				G[yi + 2].emplace_back(xi + gap + 2);
			}
			if (z & 8) {
				G[gap + xi + 3].emplace_back(xi + 3);
				G[gap + yi + 3].emplace_back(yi + 3);
			}
			else {
				G[xi + 3].emplace_back(yi + gap + 3);
				G[yi + 3].emplace_back(xi + gap + 3);
			}
			if (z & 16) {
				G[gap + xi + 4].emplace_back(xi + 4);
				G[gap + yi + 4].emplace_back(yi + 4);
			}
			else {
				G[xi + 4].emplace_back(yi + gap + 4);
				G[yi + 4].emplace_back(xi + gap + 4);
			}
		}
		else {
			if (z & 1) {
				G[gap + xi].emplace_back(yi);
				G[gap + yi].emplace_back(xi);
			}
			else {
				G[xi].emplace_back(gap + xi);
				G[yi].emplace_back(gap + yi);
			}
			if (z & 2) {
				G[gap + xi + 1].emplace_back(yi + 1);
				G[gap + yi + 1].emplace_back(xi + 1);
			}
			else {
				G[xi + 1].emplace_back(gap + xi + 1);
				G[yi + 1].emplace_back(gap + yi + 1);
			}
			if (z & 4) {
				G[gap + xi + 2].emplace_back(yi + 2);
				G[gap + yi + 2].emplace_back(xi + 2);
			}
			else {
				G[xi + 2].emplace_back(gap + xi + 2);
				G[yi + 2].emplace_back(gap + yi + 2);
			}
			if (z & 8) {
				G[gap + xi + 3].emplace_back(yi + 3);
				G[gap + yi + 3].emplace_back(xi + 3);
			}
			else {
				G[xi + 3].emplace_back(gap + xi + 3);
				G[yi + 3].emplace_back(gap + yi + 3);
			}
			if (z & 16) {
				G[gap + xi + 4].emplace_back(yi + 4);
				G[gap + yi + 4].emplace_back(xi + 4);
			}
			else {
				G[xi + 4].emplace_back(gap + xi + 4);
				G[yi + 4].emplace_back(gap + yi + 4);
			}
		}
	}

	if (TWOSAT()) {
		cout << 1 << '\n';
		for (int i = 1; i < N; i += 5) {
			cout << ans[i] + 2 * ans[i + 1] + 4 * ans[i + 2] + 8 * ans[i + 3] + 16 * ans[i + 4] << ' ';
		}
	}
	else cout << 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 6496 // C++] Cyclic antimonotonic permutations  (0) 2022.08.14
[BOJ 6134 // C++] Sunscreen  (0) 2022.08.13
[BOJ 13308 // C++] 주유소  (0) 2022.08.11
[BOJ 5568 // C++] 카드 놓기  (0) 2022.08.10
[BOJ 12758 // C++] 천상용섬  (0) 2022.08.09

+ Recent posts