ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BOJ) 부등호
    알고리즘/백준 2020. 7. 3. 16:27
    반응형

    부등호

     

    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

    댓글

Designed by Tistory.