-
반응형
부등호
2529번: 부등호
두 종류의 부등호 기호 ‘<’와 ‘>’가 k개 나열된 순서열 A가 있다. 우리는 이 부등호 기호 앞뒤에 서로 다른 한 자릿수 숫자를 넣어서 모든 부등호 관계를 만족시키려고 한다. 예를 들어, 제��
www.acmicpc.net
풀이
답은 바로 구했지만, 메모리를 너무 많이 잡고 속도가 느려서 몇 번을 다시 풀었다.
처음에는 모든 경우의 수를 다 구해서, 부등호의 갯수 n개 +1 만큼의 숫자를 뽑은 경우를 답 리스트에 넣어주었다.
이후, 정렬을 통해 양 끝에 있는 수를 출력해주었다.
코드 1 정말 별로인 코드다...
그래서 조금 고쳐보기로 했다.
String으로 다 저장해서 정렬을 하는것이 아니라, Long 타입 변수를 통해 MAX와 MIN 값을 저장해주었다.
로직 자체가 문제라서 메모리와 속도에 큰 효과를 보지 못할 것이라고 생각했지만, 더 나은 코드를 생각하는 과정이라고 생각하고 진행했다.
최대 최솟값이 앞자리가 0인 경우는 LONG 타입이기 때문에 0이 저장되지 않는다.
그래서 자릿수에 맞게 0까지 print를 해주는 메소드를 만들어서 제출했다.
코드 2 속도 측면에서는 꽤나 성능이 좋아졌다.
하지만, 여전히 메모리를 많이 잡아먹고 속도도 좋지 못하다고 생각이 들었다.
그래서 list를 빼고 생각하기로 했다.
하지만, 잘 떠오르지 않아서 질문 게시판을 참고했다.
list로 숫자를 추가하는 과정을, Long타입의 숫자에 이전 숫자를 10씩 증가시키면서 해당 숫자를 더해 하나의 숫자로 그냥 구해주었다.
또한, 0~9를 다 도는 것이 아니라, 부등호에 따라서 0~n , n~9 까지만 for문을 돌게 해주었다.
Long 타입으로 최대 최소를 구해줬기 때문에, 여기서도 0을 포함하는 print를 해야했다.
C언어에서 %0nd가 생각나서 찾아봤는데, 자바에도 String.format으로 쓸 수 있었다. ( 잘 쓰지 않아서 까먹고 있었는데, 다시 생각났다. )
코드 3 메모리와 속도가 현저히 좋아졌다.
답답한 마음이 확 풀리는 순간이었다.
brute-force 문제는 어떻게 가지치기를 하느냐가, 그리고 어떤 식으로 값을 도출하는가에 따라 정말 천차만별인것 같다.
물론 다른 알고리즘들도 마찬가지지만, brute-force는 완전 탐색을 전제로 하기 때문에, 더욱 조심할 필요가 있는 것 같다.
코드 1
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Collections; import java.util.LinkedList; public class Main { final static int NUMMAX = 10; final static String LEFT = ">"; static String[] ineqArr; static LinkedList<String> ansList; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); ineqArr = br.readLine().split(" "); solution(n); br.close(); } private static void solution(int n) { ansList = new LinkedList<>(); getAns(new boolean[NUMMAX], 0, n, new LinkedList<>()); Collections.sort(ansList, (o1, o2) -> o1.compareTo(o2) < o2.compareTo(o1) ? 1 : -1); System.out.println(ansList.poll()); System.out.println(ansList.pollLast()); } private static void getAns(boolean[] visit, int cnt, int n, LinkedList<Integer> list) { if(n <cnt) { if(list.size()>n) { LinkedList<Integer> newList = copyList(list); StringBuffer sb = new StringBuffer(); for (String ineq : ineqArr) { int leftNum = newList.poll(); int rightNum = newList.peek(); if (ineq.equals(LEFT)) { // > if (leftNum < rightNum) { return; } } else { // < if (leftNum > rightNum) { return; } } sb.append(leftNum); } sb.append(newList.poll()); ansList.offer(sb.toString()); } return; } for(int i=0; i<NUMMAX; i++) { if(!visit[i]) { visit[i] = true; list.offer(i); getAns(visit,cnt+1,n,list); visit[i] = false; list.pollLast(); } } } private static LinkedList<Integer> copyList(LinkedList<Integer> list) { LinkedList<Integer> result = new LinkedList<>(); for(int num : list) { result.offer(num); } return result; } }
코드 2
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.LinkedList; public class Main { final static int NUMMAX = 10; final static String LEFT = ">"; static String[] ineqArr; static long minAns, maxAns; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); ineqArr = br.readLine().split(" "); solution(n); br.close(); } private static void solution(int n) { minAns = Long.MAX_VALUE; maxAns = 0; getAns(new boolean[NUMMAX], 0, n, new LinkedList<>()); printNum(maxAns,n); printNum(minAns,n); } private static void printNum(long num, int n) { long div = (long) Math.pow(10,n); StringBuffer sb = new StringBuffer(); for(int i=0 ;i<=n; i++) { sb.append(num/div); num%=div; div/=10; } System.out.println(sb.toString()); } private static void getAns(boolean[] visit, int cnt, int n, LinkedList<Integer> list) { if(n <cnt) { if(list.size()>n) { StringBuffer sb = new StringBuffer(); int leftIdx =0; int rightIdx =1; for(int i=0; i<n; i++) { int leftNum = list.get(leftIdx++); int rightNum = list.get(rightIdx++); if (ineqArr[i].equals(LEFT)) { // > if (leftNum < rightNum) { return; } } else { // < if (leftNum > rightNum) { return; } } sb.append(leftNum); } sb.append(list.get(leftIdx)); maxAns = Math.max(Long.parseLong(sb.toString()),maxAns); minAns = Math.min(Long.parseLong(sb.toString()), minAns); } return; } for(int i=0; i<NUMMAX; i++) { if(!visit[i]) { visit[i] = true; list.offer(i); getAns(visit,cnt+1,n,list); visit[i] = false; list.pollLast(); } } } }
코드 3
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Main { final static int NUMMAX = 10; final static String LEFT = ">"; static String[] ineqArr; static long minAns, maxAns; static boolean[] visit; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); ineqArr = br.readLine().split(" "); solution(n); br.close(); } private static void solution(int n) { minAns = Long.MAX_VALUE; maxAns = 0; visit = new boolean[NUMMAX]; for(int i=0; i<NUMMAX; i++) { visit[i] = true; getAns(i, 0, n, i); visit[i] = false; } System.out.println(maxAns); StringBuffer sb = new StringBuffer("%0").append(n+1).append("d"); System.out.println(String.format(sb.toString(),minAns)); } private static void getAns(int now, int idx, int n, long num) { if(idx == n) { maxAns = Math.max(maxAns, num); minAns = Math.min(minAns, num); return; } if(ineqArr[idx].equals(LEFT)) { // > for(int i=0; i<now; i++) { if(!visit[i]) { visit[i] = true; getAns(i, idx + 1, n, num * 10 + i); visit[i] = false; } } } else { // < for(int i=NUMMAX-1; i>now; i--) { if(!visit[i]) { visit[i] = true; getAns(i, idx + 1, n, num * 10 + i); visit[i] = false; } } } } }
반응형'알고리즘 > 백준' 카테고리의 다른 글
BOJ) 연산자 끼워넣기 (0) 2020.07.05 BOJ) 벽 부수고 이동하기 4 (0) 2020.07.03 BOJ) 스타트와 링크 (2) 2020.07.02 BOJ) 에너지 모으기 (0) 2020.07.02 BOJ) 연구소 (0) 2020.07.02