※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 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 |