솔직히 풀이하는데 오래 걸렸다. (2~3시간)
괄호의 중복을 허용하지 않는 것이 다행인 문제라고 느껴진다.
숫자와 마주치면
괄호를 넣거나
넣지 않는다.
특히, 이미 괄호 안에 들어간 숫자인 경우 넣으면 안된다
3+8*9
여기서 3을 보고, 괄호를 해야겠다 생각을 함.
그런데 8을 마주함 ! -> 하지만 8은 이미 괄호에 들어간 상태
(3+8)
🧭🧭 N이 19이하 → 1+2*9 → 숫자 10개, 연산자 9개 → 최대 2^10가지정도이기 때문에 완전탐색이 가능할 듯 하다. 🧭🧭
숫자를 마주칠 때 마다, 1. 현숫자에 대해 괄호를 넣을 것 2. 현숫자에 대해 괄호를 넣지 않을 것 —> 이 두가지 경우 모두를 해 보아야 한다.
재귀함수를 사용할 것이고, 재귀함수에서는, int idxes[3]을 사용한다.
idxes[0,+연산자의 index,0]을 넣어둔다. 0은 이제까지의 연산결과이고, idxes[1]은 연산자이다
매 번 idexes는 idxes[0]과 idxes[1] 이 채워져 있도록 한다.
여기서 '1. 현 숫자에 대해 괄호를 넣을 것 ' —> 의 경우에는, express(idx) express(idx+1) express(idx+2) 의 연산이 일어나는 것이다. ( 이 문제는, 괄호의 중첩이 없기에 , 바로 이 연산 결과를 return해 오도록 한다 )
여기서 2. 현 숫자에 대해 괄호를 넣지 않을 것
숫자가 아닌 경우, → 연산자인 경우, → 연산자의 index를 idxes[1]에 저장한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Deque;
import java.util.LinkedList;
public class Main{
public static int n;
public static StringBuilder sb = new StringBuilder("+");
public static String express; // express길이는 원래식길이+1
// 원래식이 길이가 3이면 -> 4가 되고, 마지막 idx는 3이되니까..
public static int max =Integer.MIN_VALUE;
public static void Setting() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
sb.append(br.readLine());
express = sb.toString();
//"_3+8*7-9*2"
// 0123456789 -> 홀수인 idx에만 숫자가 위치한다.
}
// idxes[0] 에는 항상 값이 있으면 좋겠다.. idxes[1]에는 '+'를 해서 첫 번째 호출 때 줬으면 좋겠다.
// idxes[0] 에는 항상 이제까지의 값이 존재한다.
// 3개 단위로만 연산을 하면 된다.
public static void solve(int idx,int[] idxes){
if(idx>n){
// max인지 체크한다.
if(max<idxes[0]) max = idxes[0];
return;
}
int[] next = new int[2];
int temp =0;
// 정수인지 확인 : +,-,* 이 ascii코드상 더 작은 수를 갖는다.
// 정수인 경우 1. 이미 괄호가 쳐져 있는 경우
if(express.charAt(idx)-'0'>=0){
// 1. 괄호를 쳐서 넘길 것인가 -> 먼저 괄호 연산 값을 얻어오고, 다음 호출하는 것은.. 현재 idx +3
// 괄호를 쳐서 넘기려면 현재 idx가 정수임에도, n보다작은 idx여야 함.
if(idx<n){
// 현재 idx부터 괄호를 쳤을 때 연산되는 값 -> temp
temp = cal(express.charAt(idx)-'0',express.charAt(idx+2)-'0',idx+1);
// idxes로 넘어온 값들 과 temp를 연산시키기
next[0]=cal(idxes[0],temp,idxes[1]);
solve(idx+3,next);
}
// 2. 괄호를 치지 않고 넘길 것인가 --> 괄호를 치지 않고 넘길 것인가에서도 경우
next[0]=cal(idxes[0],express.charAt(idx)-'0',idxes[1]);
solve(idx+1,next);
}
else{
next[0]=idxes[0];
// 무조건 이 연산자를 추가 해 주도록 해야 함.
next[1]=idx;
solve(idx+1,next);
}
}
// opidx는 연산자의 idx
public static int cal(int n1,int n2,int opidx){
char op = sb.charAt(opidx);
switch (op){
case '+':
return n1+n2;
case '-':
return n1-n2;
case '*':
return n1*n2;
}
return 0;
}
public static void main(String[] args) throws IOException {
Setting();
if(n==1){
max = express.charAt(1)-'0';
System.out.println(max);
return;
}
solve(1,new int[]{0,0,0});
System.out.println(max);
}
}
아하 그렇다. 결국 내가 - 완전탐색 + 재귀함수 + 어떤 값을 넘겨줘야 한다 —> 라고 생각했던 것도
매 번 두 가지 outgoing path가 존재하였기 때문이다. DFS 문제가 맞다.
그리고 내가 계속해서 고민했던 것은, "이제까지의 연산값" 만을 pass해 줄 것인가, (n1 op n2)에서 (n1, op) 를 계속 해서 넘겨 줘야 하는 가 였다.
나는 결국 (n1,op)를 계속해서 넘겨주는 것을 택하였다. → 이 과정에서 solve함수를 호출 할 때 마다 int[3]의 배열을 생성하는 과정을 거쳐야 했다.