출처: https://snupi.tistory.com/31 [SNUPI]

BOJ9019.java

// https://www.acmicpc.net/problem/9019
// 20.8.12. ventania1680
// BFS

package BOJ;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class BOJ9019 {
    static boolean[] visited = new boolean[10001];
    static String[] path = new String[10001];

    static int f(int num, char c) {
        switch (c) {
            case 'D':
                return (num * 2) % 10000;
            case 'S':
                return (num == 0) ? 9999 : --num;
            case 'L':
                return (num % 1000) * 10 + num / 1000;
            case 'R':
                return num / 10 + num % 10 * 1000;
        }
        return 0;
    }

    public static void solution() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        Queue<Integer> q = new LinkedList<>();
        while (t-- > 0) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());

            Arrays.fill(path, "");
            Arrays.fill(visited, false);
            q.clear();

            q.add(a);
            visited[a] = true;
            int parent = 0, cur = 0;
            while (!q.isEmpty() && q.peek() != b) {
                parent = q.peek();
                cur = f(parent, 'D');
                if (!visited[cur]) {
                    visited[cur] = true;
                    path[cur] = path[parent] + "D";
                    q.add(cur);
                }

                cur = f(parent, 'S');
                if (!visited[cur]) {
                    visited[cur] = true;
                    path[cur] = path[parent] + "S";
                    q.add(cur);
                }

                cur = f(parent, 'L');
                if (!visited[cur]) {
                    visited[cur] = true;
                    path[cur] = path[parent] + "L";
                    q.add(cur);
                }

                cur = f(parent, 'R');
                if (!visited[cur]) {
                    visited[cur] = true;
                    path[cur] = path[parent] + "R";
                    q.add(cur);
                }
                q.poll();
            }
            sb.append(path[q.peek()] + "\n");
        }
        System.out.print(sb.toString());
    }
}

 

BFS 알고리즘을 사용하는 문제.

 

visited 배열에 방문 여부 저장, path 배열에 해당 인덱스까지 경로(명령어) 저장.

 

Arrays.fill 메소드로 path, visited 배열을 초기화한다. (새로운 배열을 할당하면 메모리 초과 발생함)

큐 역시 메모리 초과를 방지하기 위해서 clear 메소드로 큐를 초기화한다.

 

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

 

9019번: DSLR

문제 네 개의 명령어 D, S, L, R 을 이용하는 간단한 계산기가 있다. 이 계산기에는 레지스터가 하나 있는데, 이 레지스터에는 0 이상 10,000 미만의 십진수를 저장할 수 있다. 각 명령어는 이 레지스�

www.acmicpc.net

https://github.com/ventania1680/algorithm/blob/82f17ff172e90d97e80b82e4ea59404f65f4a4d1/Algorithm/src/BOJ/BOJ9019.java

 

ventania1680/algorithm

Contribute to ventania1680/algorithm development by creating an account on GitHub.

github.com

 

'Algorithm > BOJ' 카테고리의 다른 글

BOJ10026 / 적록색약  (0) 2020.08.14
BOJ9205 / 맥주 마시면서 걸어가기  (0) 2020.08.13
BOJ6064 / 카잉 달력  (0) 2020.08.11
BOJ1654 / 랜선 자르기  (0) 2020.08.10
BOJ1436 / 영화감독 숌  (0) 2020.08.08

BOJ6064.java

// https://www.acmicpc.net/problem/6064
// 20.8.11. ventania1680
package BOJ;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BOJ6064 {
    public static int findGCD(int m, int n) {
        while (n > 0) {
            int r = m % n;
            m = n;
            n = r;
        }
        return m;
    }

    public static void solution() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        while(t-- > 0) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int m = Integer.parseInt(st.nextToken());
            int n = Integer.parseInt(st.nextToken());
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());

            int gcd = m * n / (m > n ? findGCD(m, n) : findGCD(n, m));
            int tx = x, ty = x % n;
            if (ty == 0) ty = n;
            int answer = x;
            while (ty != y && answer <= x + gcd) {
                ty += (m - n);
                if (m > n) {
                    ty %= n;
                }
                else {
                    ty = Math.floorMod(ty, n);
                }
                if (ty == 0) ty = n;
                answer += m;
            }
            if (ty != y)
                answer = -1;
            sb.append(answer + "\n");
        }
        System.out.print(sb);
    }
}

 

최소공배수를 기점으로 tx, ty가 반복된다. 이를 이용하여 반복문 탈출조건을 정할 수 있다.

 

m년이 지날 때마다 y는 m - n 만큼 더해진다.  y의 범위는 1 ~ n이므로 모듈러연산을 이용하여 범위를 제한할 수 있다.

 

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

 

6064번: 카잉 달력

문제 최근에 ICPC 탐사대는 남아메리카의 잉카 제국이 놀라운 문명을 지닌 카잉 제국을 토대로 하여 세워졌다는 사실을 발견했다. 카잉 제국의 백성들은 특이한 달력을 사용한 것으로 알려져 있�

www.acmicpc.net

https://github.com/ventania1680/algorithm/blob/master/Algorithm/src/BOJ/BOJ6064.java

 

ventania1680/algorithm

Contribute to ventania1680/algorithm development by creating an account on GitHub.

github.com

 

'Algorithm > BOJ' 카테고리의 다른 글

BOJ10026 / 적록색약  (0) 2020.08.14
BOJ9205 / 맥주 마시면서 걸어가기  (0) 2020.08.13
BOJ9019 / DSLR  (0) 2020.08.12
BOJ1654 / 랜선 자르기  (0) 2020.08.10
BOJ1436 / 영화감독 숌  (0) 2020.08.08

BOJ1654.java

// https://www.acmicpc.net/problem/1654
// 20.8.10. ventania1680
// 이분탐색 변형으로 풀이 가능
package BOJ;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BOJ1654 {
    public static void solution() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int k = Integer.parseInt(st.nextToken());
        int n = Integer.parseInt(st.nextToken());

        long[] arr = new long[k];
        long sum = 0;
        for (int i = 0; i < k; i++) {
            arr[i] = Integer.parseInt(br.readLine());
            sum += arr[i];
        }

        long high = sum / n;
        long low = 1;
        long half = (high + low) / 2;
        int cnt;
        long answer = 0;
        while(high >= low) {
            cnt = 0;
            for (int i = 0; i < k; i++) {
                cnt += arr[i] / half;
            }
            if (cnt >= n) {
                if (answer < half) answer = half;
                low = half + 1;
                half = (high + low) / 2;
            }
            else if (cnt < n) {
                high = half - 1;
                half = (high + low) / 2;
            }
        }
        System.out.println(answer);
    }
}

 

문제에 주어진 랜선 길이의 범위가 1~(2^31)-1 까지이므로 오버플로우 발생을 고려해서 자료형으로 long을 사용했다.

 

이분탐색시 2^31을 high로 잡아야하지만, 문제 조건에 따라 랜선의 길이로 가능한 최댓값은 모든 랜선의 길이를 n(만들어야 하는 랜선의 개수)으로 나눈 값이 된다.

 

이후 이분탐색을 시작한다. 원래 이분탐색이라면 cnt == n 이 된 시점에서 값을 반환해야하나, 문제 조건에 따라 가능한 최대 길이를 찾아야하므로 cnt == n인 경우에도 탐색을 계속한다.

 

high와 low가 같거나 low가 더 커지는 경우 반복문을 탈출하고 그 때 answer에 저장된 값이 문제의 답이다.

 

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

 

1654번: 랜선 자르기

첫째 줄에는 오영식이 이미 가지고 있는 랜선의 개수 K, 그리고 필요한 랜선의 개수 N이 입력된다. K는 1이상 10,000이하의 정수이고, N은 1이상 1,000,000이하의 정수이다. 그리고 항상 K ≦ N 이다. 그

www.acmicpc.net

https://github.com/ventania1680/algorithm/blob/master/Algorithm/src/BOJ/BOJ1654.java

 

ventania1680/algorithm

Contribute to ventania1680/algorithm development by creating an account on GitHub.

github.com

 

'Algorithm > BOJ' 카테고리의 다른 글

BOJ10026 / 적록색약  (0) 2020.08.14
BOJ9205 / 맥주 마시면서 걸어가기  (0) 2020.08.13
BOJ9019 / DSLR  (0) 2020.08.12
BOJ6064 / 카잉 달력  (0) 2020.08.11
BOJ1436 / 영화감독 숌  (0) 2020.08.08

BOJ1436.java

// https://www.acmicpc.net/problem/1436
// 20.8.8. ventania1680
// 브루트포스로 해결 가능

package BOJ;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class BOJ1436 {
    public static void solution() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());

        final int doom = 666;
        if (n == 1) {
            System.out.println(doom);
            return;
        }

        int tmp, count = 1;
        for (int i = 1666; i < 3000000; i++) {
            tmp = i;
            while (tmp >= 666) {
                if ((tmp - doom) % 1000 == 0) {
                    if (++count == n) System.out.println(i);
                    break;
                }
                tmp /= 10;
            }
        }
    }
}

 

완전탐색(브루트포스)로 해결 가능한 문제.

 

i를 10으로 계속해서 나누면서 끝 세자리가 666인지 아닌지를 판단한다.

 

666이 나올 때마다 count해주고 n번째 수를 출력한다.

 

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

 

1436번: 영화감독 숌

666은 종말을 나타내는 숫자라고 한다. 따라서, 많은 블록버스터 영화에서는 666이 들어간 제목을 많이 사용한다. 영화감독 숌은 세상의 종말 이라는 시리즈 영화의 감독이다. 조지 루카스는 스타

www.acmicpc.net

https://github.com/ventania1680/algorithm/blob/master/Algorithm/src/BOJ/BOJ1436.java

 

ventania1680/algorithm

Contribute to ventania1680/algorithm development by creating an account on GitHub.

github.com

 

 

'Algorithm > BOJ' 카테고리의 다른 글

BOJ10026 / 적록색약  (0) 2020.08.14
BOJ9205 / 맥주 마시면서 걸어가기  (0) 2020.08.13
BOJ9019 / DSLR  (0) 2020.08.12
BOJ6064 / 카잉 달력  (0) 2020.08.11
BOJ1654 / 랜선 자르기  (0) 2020.08.10

문제 설명

어떤 숫자에서 k개의 수를 제거했을 때 얻을 수 있는 가장 큰 숫자를 구하려 합니다.

예를 들어, 숫자 1924에서 수 두 개를 제거하면 [19, 12, 14, 92, 94, 24] 를 만들 수 있습니다. 이 중 가장 큰 숫자는 94 입니다.

문자열 형식으로 숫자 number와 제거할 수의 개수 k가 solution 함수의 매개변수로 주어집니다. number에서 k 개의 수를 제거했을 때 만들 수 있는 수 중 가장 큰 숫자를 문자열 형태로 return 하도록 solution 함수를 완성하세요.

 

제한 조건

  • number는 1자리 이상, 1,000,000자리 이하인 숫자입니다.
  • k는 1 이상 number의 자릿수 미만인 자연수입니다.

입출력 예

number k return
"1924" 2 "94"
"1231234" 3 "3234"
"4177252841" 4 "775841"

 

Greedy02.java

// https://programmers.co.kr/learn/courses/30/lessons/42883
// 20.8.7. ventania1680
package Programmers;

import java.util.Stack;

public class Greedy02 {
    public static String solution(String number, int k) {
        char[] answer = new char[number.length() - k];
        Stack<Character> s = new Stack<>();

        for (int i = 0; i < number.length(); i++) {
            char c = number.charAt(i);
            while(!s.isEmpty() && s.peek() < c && k-- > 0)
                s.pop();
            s.push(c);
        }

        for (int i = 0; i < answer.length; i++)
            answer[i] = s.get(i);

        return new String(answer);
    }
}

 

스택 클래스 사용과 그리디 알고리즘으로 간단하게 풀 수 있는 문제.

 

스택 최상단에 있는 수가 현재 위치의 수보다 작은 경우에 팝(POP)한다.

 

https://programmers.co.kr/learn/courses/30/lessons/42883

 

코딩테스트 연습 - 큰 수 만들기

 

programmers.co.kr

https://github.com/ventania1680/algorithm/blob/master/Algorithm/src/Programmers/Greedy02.java

 

ventania1680/algorithm

Contribute to ventania1680/algorithm development by creating an account on GitHub.

github.com

 

문제 설명

 

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.

전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

 

제한사항

  • 전체 학생의 수는 2명 이상 30명 이하입니다.
  • 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
  • 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.

입출력 예

n lost reserve return
5 [2, 4] [1, 3, 5] 5
5 [2, 4] [3] 4
3 [3] [1] 2

입출력 예 설명

예제 #1
1번 학생이 2번 학생에게 체육복을 빌려주고, 3번 학생이나 5번 학생이 4번 학생에게 체육복을 빌려주면 학생 5명이 체육수업을 들을 수 있습니다.

예제 #2
3번 학생이 2번 학생이나 4번 학생에게 체육복을 빌려주면 학생 4명이 체육수업을 들을 수 있습니다.

 

Greedy01.java

// https://programmers.co.kr/learn/courses/30/lessons/42862
// 20.8.7. ventania1680
package Programmers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Greedy01 {
    public static int solution(int n, int[] lost, int[] reserve) {
        int answer = n - lost.length;
        boolean[] res = new boolean[31];
        Arrays.fill(res, false);
        Arrays.sort(lost);
        for (int i = 0; i < reserve.length; i++) {
            res[reserve[i]] = true;
        }
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < lost.length; i++)
            list.add(lost[i]);

        for (int i = 0; i < list.size(); i++) {
            int tmp = list.get(i);
            if (res[tmp]) {
                list.remove(i--);
                res[tmp] = false;
                answer++;
            }
        }
        for (int i = 0; i < list.size(); i++) {
            int tmp = list.get(i);
            if (res[tmp - 1]) {
                res[tmp - 1] = false;
                answer++;
            }
            else if (res[tmp + 1]) {
                res[tmp + 1] = false;
                answer++;
            }
        }
        return answer;
    }
}

 

문제 조건에 따라 학생의 수는 최대 30명, 즉 1번부터 30번 학생까지 있다.

 

여벌의 체육복을 가져온 학생을 boolean 배열로 표현했다.

 

여벌 체육복을 가져온 학생이 체육복을 도난당한 경우에는 다른 학생에게 빌려줄 수 없으므로, 해당 경우를 먼저 제외한다.

 

처음에는 lost 배열을 그대로 사용하여 답을 구했더니 여벌 체육복을 가져오고 체육복을 도난당한 학생을 두 번 카운트하게 되어 이를 ArrayList를 사용해서 리스트에서 제거하는 방식으로 중복을 방지했다.

 

https://programmers.co.kr/learn/courses/30/lessons/42862

 

코딩테스트 연습 - 체육복

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번�

programmers.co.kr

https://github.com/ventania1680/algorithm/blob/master/Algorithm/src/Programmers/Greedy01.java

 

ventania1680/algorithm

Contribute to ventania1680/algorithm development by creating an account on GitHub.

github.com

 

문제 설명

 

Leo는 카펫을 사러 갔다가 아래 그림과 같이 중앙에는 노란색으로 칠해져 있고 테두리 1줄은 갈색으로 칠해져 있는 격자 모양 카펫을 봤습니다.

Leo는 집으로 돌아와서 아까 본 카펫의 노란색과 갈색으로 색칠된 격자의 개수는 기억했지만, 전체 카펫의 크기는 기억하지 못했습니다.

Leo가 본 카펫에서 갈색 격자의 수 brown, 노란색 격자의 수 yellow가 매개변수로 주어질 때 카펫의 가로, 세로 크기를 순서대로 배열에 담아 return 하도록 solution 함수를 작성해주세요.

 

제한사항

  • 갈색 격자의 수 brown은 8 이상 5,000 이하인 자연수입니다.
  • 노란색 격자의 수 yellow는 1 이상 2,000,000 이하인 자연수입니다.
  • 카펫의 가로 길이는 세로 길이와 같거나, 세로 길이보다 깁니다.

입출력 예

brown yellow return
10 2 [4, 3]
8 1 [3, 3]
24 24 [8, 6]

 

BF03.java

// https://programmers.co.kr/learn/courses/30/lessons/42842
// 20.8.6. ventania1680
package Programmers;

public class BF03 {
    public static int[] solution(int brown, int yellow) {
        int sum = brown + yellow;
        for (int row = 3; row < sum; row++) {
            if (sum % row == 0) {
                int col = sum / row;
                if (row * 2 + col * 2 - 4 == brown) {
                    return new int[] {col, row};
                }
            }
        }
        return null;
    }
}

 

완전탐색으로 간단하게 해결할 수 있는 문제.

 

모든 격자의 개수를 나눌 수 있는 수가 곧 가능한 가로, 세로의 크기가 된다.

 

테두리가 곧 갈색 격자의 개수이므로 (가로 * 2 + 세로 * 2 - 4 = 갈색 격자 개수)라는 식이 성립한다.

 

가능한 모든 가로, 세로 크기에 대해서 위 식을 만족하는지 검사하여 문제의 답을 구할 수 있다.

 

https://programmers.co.kr/learn/courses/30/lessons/42842

 

코딩테스트 연습 - 카펫

Leo는 카펫을 사러 갔다가 아래 그림과 같이 중앙에는 노란색으로 칠해져 있고 테두리 1줄은 갈색으로 칠해져 있는 격자 모양 카펫을 봤습니다. Leo는 집으로 돌아와서 아까 본 카펫의 노란색과 ��

programmers.co.kr

 

https://github.com/ventania1680/algorithm/blob/master/Algorithm/src/Programmers/BF03.java

 

ventania1680/algorithm

Contribute to ventania1680/algorithm development by creating an account on GitHub.

github.com

 

+ Recent posts