🎲
<C++/백준 16637> 괄호 추가하기
January 15, 2025
<C++/백준 16637> 괄호 추가하기
🥇 골드 3
📌 문제 패턴 인식
연산자가 등장할 때마다 2가지 선택(괄호 유무)이 가능하고, 이전까지의 계산 결과를 기반으로 다음 선택을 해야 하는 유형
🔍 특징
- 수식에서 ”누적되는 값 + 다음 선택” 형태
psum(prefix_sum, 누적합 문제!)
- 괄호 위치 결정 문제
- 매 시점 2가지 선택 가능
💡 핵심 아이디어
1. 누적값 + 방향 결정
- 지금까지의 계산 결과를 가지고
- 다음에 어떤 연산을 할지 결정!
(재귀함수)
go(위치, 누적값)
형태로 구현
2. 매 시점 2가지 선택
- 괄호 없이 그냥 계산
- 다음 두 수를 묶어서 계산 (인덱스 주의)
🔨 코드 구현
기본 뼈대
void go(int here, int sum) {
// 1. 끝에 도달
if(here == 마지막) {
ret = max(ret, sum);
return;
}
// 2. 괄호 없이 계산
go(here + 1, 계산결과);
// 3. 괄호 사용해서 계산
if(다음숫자가_2개이상_남았으면) {
go(here + 2, 계산결과);
}
}
주요 자료구조
vector<int> num; // 숫자 저장
vector<char> oper_str; // 연산자 저장
🎯 문제 해결 접근법
1. 첫 번째 단계
- “누적값 + 선택” 패턴 인식하기
go(위치, 누적값)
형태 떠올리기
2. 두 번째 단계
- 매 위치에서 가능한 선택지 정리
- 재귀로 모든 경우 탐색
👀 비슷한 문제 패턴
- 수식 계산 + 괄호 추가/삭제
- 매 시점 2가지 이상 선택지
- 이전 결과로 다음 선택하는 경우
📝 예시 입출력
입력: 3+8*7
출력: 77
경로1: 3+8*7 = 11*7 = 77
경로2: 3+(8*7) = 3+56 = 59
⚠️ 주의사항
- 인덱스 범위 체크 필수
- 괄호 안에는 연산자 하나만
- 중첩된 괄호 불가능
정답 코드 (디버깅 코드 포함)
#include <bits/stdc++.h>
using namespace std;
// 숫자와 연산자를 따로 저장할 벡터
vector<int> num; // 숫자만 저장하는 벡터 (ex: "3+8*7" => {3, 8, 7}
vector<char> oper_str; // 연산자만 저장하는 벡터 (ex: "3+8*7" => {'+', '*'}
// 전역 변수 선언
int n;
int ret = INT_MIN; // 최댓값을 저장할 변수 (충분히 작은 값으로 초기화)
string s;
// 연산을 수행하는 함수
// a: 연산자
// b, c: 피연산자 (숫자)
int oper(char a, int b, int c) {
cout << "연산 수행: " << b << a << c << "=";
int result;
if(a == '+') result = b + c;
if(a == '-') result = b - c;
if(a == '*') result = b * c;
cout << result << '\n';
return result;
}
// 재귀적으로 모든 경우를 탐색하는 함수
// here: 현재 보고 있는 연산자의 위치
// _num: 현재까지 계산된 결과
void go(int here, int _num) {
cout << "\n현재 위치(here): " << here << ", 현재까지의 계산값(_num): " << _num << '\n';
// 기저 사례: 마지막 숫자까지 왔을 때
if(here == num.size() - 1) {
cout << "끝에 도달! 현재 ret: " << ret << ", 새로운 값: " << _num << "\n";
ret = max(ret, _num);
return;
}
// 1. 괄호 없이 순서대로 계산하는 경우
cout << "괄호 없이 계산하는 경우, go(" << here + 1 << ", oper(" << oper_str[here] << ", " << _num << ", " << num[here + 1] << ")) 호출\n";
go(here + 1, oper(oper_str[here], _num, num[here + 1]));
// 2. 다음 두 숫자를 괄호로 묶어서 계산하는 경우
if(here + 2 <= num.size() - 1) { // 단, 앞으로 숫자가 2개 이상 남아있어야 함
cout << "괄호 사용하는 경우\n"; // 디버깅
cout << "괄호 안을 먼저 계산: " << num[here + 1] << oper_str[here + 1] << num[here + 2] << '\n';
// 괄호 안 계산을 먼저 수행
int temp = oper(oper_str[here + 1], num[here + 1], num[here + 2]);
// 괄호 계산 결과와 현재까지의 값을 연산
go(here + 2, oper(oper_str[here], _num, temp));
}
return;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n >> s;
// 수식 문자열에서 숫자와 연산자를 분리하여 저장
for(int i = 0; i < n; i++) {
// 짝수 인덱스: 숫자
if(i % 2 == 0) {
num.push_back(s[i] - '0'); // 문자를 숫자로 변환하여 저장
} else { // 홀수 인덱스: 연산자
oper_str.push_back(s[i]);
}
}
// 계산 시작 (첫 번째 숫자를 초기값으로)
cout << "\n 계산 시작: \n";
go(0, num[0]);
// 결과 출력
cout << "\n최종 결과: " << ret << '\n';
return 0;
}