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

 

이번에 볼 문제는 백준 1023번 문제인 괄호 문자열이다.
문제는 아래 링크를 확인하자.

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

 

1023번: 괄호 문자열

괄호 문자열은 다음과 같이 정의 한다. 빈 문자열은 괄호 문자열이다. S가 괄호 문자열일 때, (S)도 괄호 문자열이다. S와 T가 괄호 문자열이라면, ST도 괄호 문자열이다. 모든 괄호 문자열은 위의

www.acmicpc.net

'('와 ')'로 이루어진 길이가 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

+ Recent posts