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

 

이번에 볼 문제는 백준 8111번 문제인 0과 1이다.
문제는 아래 링크를 확인하자.

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

 

8111번: 0과 1

각각의 테스트 케이스마다 N의 배수이면서, 구사과가 좋아하는 수를 아무거나 출력한다. 만약, 그러한 수가 없다면 BRAK을 출력한다.

www.acmicpc.net

이 문제에서는 0과 1로만 이루어진 100자리 이하의 자연수 중 N의 배수를 찾는 문제이다.

 

100자리의 자연수를 들고 있기는 어려우므로, N의 나머지만을 보관하며 BFS를 해주자.

 

BFS를 하면 작은 자릿수의 숫자부터 탐색을 하게 되고, 이미 방문했던 "나머지"를 갖는 숫자가 나온다면 이 수는 이미 이전 단계에서 나온 같거나 작은 자릿수의 먼저 방문한 수와 이후로 똑같은 나머지들을 갖는 수들을 탐색해나가게 되므로 pruning(가지치기)을 해주자.

 

이와 같이 탐색하면 N별로 나올 수 있는 서로 다른 나머지 N개만을 탐색하고 탐색을 종료하게 되므로 실제로 방문하는 수의 경우의 수가 적어지므로 이 문제를 충분히 해결할 수 있다.

 

단, N의 범위가 100만까지 가능한 #8112번 문제는 아래 코드와 같이 제출하면 시간초과가 난다. 그 이유는 문자열을 계속 복사하여 집어넣는 데에 시간이 많이 소요되기 때문이다.

 

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

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
using namespace std;

int visited[20001];

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

	int N; cin >> N;
	while (N--) {
		memset(visited, 0, sizeof(visited));
		int x; cin >> x;
		if (x == 1) cout << 1 << '\n';
		else {
			queue<pair<string, int>> que;
			que.push({ "1",1 });
			while (!que.empty()) {
				string s = que.front().first; int r = que.front().second; que.pop();
				if (r == 0) {
					if (s.length() <= 100) cout << s << '\n';
					else cout << "BRAK\n";
				}
				if (!visited[(r * 10) % x]) {
					visited[(r * 10) % x] = 1;
					que.push({ s + "0", (r * 10) % x });
				}
				if (!visited[(r * 10 + 1) % x]) {
					visited[(r * 10 + 1) % x] = 1;
					que.push({ s + "1", (r * 10 + 1) % x });
				}
			}
			if (!visited[0]) cout << "BRAK\n";
		}
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2583 // C++] 영역 구하기  (0) 2021.10.13
[BOJ 8112 // C++] 0과 1 - 2  (0) 2021.10.12
[BOJ 2800 // C++] 괄호 제거  (0) 2021.10.10
[BOJ 1595 // C++] 북쪽나라의 도로  (0) 2021.10.09
[BOJ 5913 // C++] 준규와 사과  (0) 2021.10.08

+ Recent posts