※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1023번 문제인 괄호 문자열이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/1023
'('와 ')'로 이루어진 길이가 N인 올바르지 않은 괄호문자열 중 사전순 K번째 문자열을 출력하는 문제이다.
매 순간 '('를 다음에 썼을 때 그 이후에 문자열을 이어 작성해 찾을 수 있는 올바르지 않은 괄호문자열의 개수를 이용하면 다음으로 '('를 쓸지를 결정할 수 있다. 이를 반복해 문제를 해결하자.
위와 같은 올바르지 않은 괄호문자열의 개수는 (가능한 모든 문자열의 개수) - (올바른 괄호문자열의 개수)로 구할 수 있다. 올바른 괄호문자열의 개수는 카탈란 수(Catalan number)을 활용해 계산해낼 수 있다.
앞서 나온 '('의 개수보다 ')'의 개수가 더 많아지는 순간이 생긴다면 그 뒤로 문자를 어떻게 배치하더라도 올바른 괄호 문자열이 될 수 없음에 유의하자. 또한 이 문제에서 K값의 기준이 1-based index가 아닌 0-based index 기준임에 유의하자. (이는 "예제 입력1"을 통해 알 수 있다.)
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
ll dp[26][26];
void init() {
for (int i = 0; i < 26; i++) {
dp[i][0] = 1;
for (int j = 1; j <= i; j++) {
dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
}
}
}
int N; ll K;
int l, r;
void func() {
vector<char> stk;
while (N--) {
if (K & 1) stk.emplace_back(')');
else stk.emplace_back('(');
K >>= 1;
}
while (!stk.empty()) {
cout << stk.back();
stk.pop_back();
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
init();
cin >> N >> K;
if (N & 1) {
func();
return 0;
}
l = r = N / 2;
if (K >= (1LL << N) - dp[l][r]) {
cout << -1;
return 0;
}
while (l) {
N--;
if ((1LL << (l + r - 1)) - dp[r][l - 1] > K) {
cout << '(';
l--;
}
else {
K -= (1LL << (l + r - 1)) - dp[r][l - 1];
cout << ')';
r--;
if (l > r) {
func();
return 0;
}
}
}
func();
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 1398 // C++] 동전 문제 (0) | 2023.06.27 |
---|---|
[BOJ 5549 // C++] 행성 탐사 (0) | 2023.06.26 |
[BOJ 1138 // C++] 한 줄로 서기 (0) | 2023.06.24 |
[BOJ 1103 // C++] 게임 (0) | 2023.06.23 |
[BOJ 7791 // C++] KBTU party (0) | 2023.06.22 |