diff --git "a/junghyunwoo/4th/week5/BOJ22988_\354\236\254\355\231\234\354\232\251\354\272\240\355\216\230\354\235\270.java" "b/junghyunwoo/4th/week5/BOJ22988_\354\236\254\355\231\234\354\232\251\354\272\240\355\216\230\354\235\270.java" new file mode 100644 index 0000000..13a03c5 --- /dev/null +++ "b/junghyunwoo/4th/week5/BOJ22988_\354\236\254\355\231\234\354\232\251\354\272\240\355\216\230\354\235\270.java" @@ -0,0 +1,61 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.StringTokenizer; + +/** + * [BOJ] 재활용 캠페인 / Gold 2 / 25m + * - 304 ms + * - 투 포인터 + * - 헤어 에센스 3 개를 합치면 항상 가득 참 + * - 1 개로 이미 가득 찬 헤어에센스 수 + * - + 2 개로 교환하여 가득 채울 수 있는 경우의 수 + * - + 나머지 헤어에센스 / 3 + * - 헤어에센스 정렬 후 뒤에서부터 가득 찬 헤어에센스 제외 + * - 투 포인터 : 2 개로 교환하여 가득 채울 수 있는 경우의 수 계산 + * - left 와 right 로 가득 채울 수 있으면 left 증가 right 감소 + * - 가득 채울 수 없으면 left 만 증가 + * */ +public class BOJ22988_재활용캠페인 { + public static void main(String[] args) throws IOException { + int n; + int i; + int cnt; + int full; + int left; + int right; + long x; + long half; + long[] arr; + BufferedReader br; + StringTokenizer st; + + br = new BufferedReader(new InputStreamReader(System.in)); + st = new StringTokenizer(br.readLine(), " ", false); + n = Integer.parseInt(st.nextToken()); + x = Long.parseLong(st.nextToken()); // 헤어에센스 용기 용량 + arr = new long[n + 1]; + st = new StringTokenizer(br.readLine(), " ", false); + for (i = 1; i <= n; i++) { // 헤어에센스 잔여량 입력 + arr[i] = Long.parseLong(st.nextToken()); + } + Arrays.sort(arr); // 헤어에센스 정렬 + for (right = n; arr[right] == x; right--); // 뒤에서부터 가득 찬 헤어에센스 제외 + full = n - right; // 1 개로 이미 가득 찬 헤어에센스 수 + cnt = 0; // 2 개로 교환하여 가득 채울 수 있는 경우의 수 계산 + half = x >> 1; + if ((x & 1L) == 0L) { + half--; + } // left 와 right 합이 half 를 초과해야 교환하여 가득 채움 + left = 1; + while (left < right) { // 투 포인터 + if (arr[left] + arr[right] > half) { // left 와 right 로 가득 채울 수 있으면 + cnt++; // 2 개로 교환하여 가득 채울 수 있는 경우의 수 + right--; // right 감소 + } + left++; // left 증가 + } + System.out.print(full + cnt + (n - full - (cnt << 1)) / 3); // 헤어 에센스 3 개를 합치면 항상 가득 참 + } +} diff --git "a/junghyunwoo/4th/week5/BOJ2662_\352\270\260\354\227\205\355\210\254\354\236\220.java" "b/junghyunwoo/4th/week5/BOJ2662_\352\270\260\354\227\205\355\210\254\354\236\220.java" new file mode 100644 index 0000000..2d64b4e --- /dev/null +++ "b/junghyunwoo/4th/week5/BOJ2662_\352\270\260\354\227\205\355\210\254\354\236\220.java" @@ -0,0 +1,81 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +/** + * [BOJ] 기업투자 / Gold 2 / 15m + * - 100 ms + * - Knapsack + * - 각 기업별, 투자 액수별 DP 수행 + * - 새로운 이익 계산 시 이전 기업까지의 결과만 참조 + * - 이익 크기 비교는 현재까지의 결과에서 비교 + * - 이익이 업데이트 되면 해당 위치에 마지막 투자 액수 저장 + * - 최대 이익 출력 후 마지막 투자 액수를 거꾸로 따라가면서 + * - 각 기업에 투자한 액수 추적 + * */ +public class BOJ2662_기업투자 { + private static final char SPACE = ' '; + private static final char LINE_BREAK = '\n'; + + public static void main(String[] args) throws IOException { + int n; + int m; + int i; + int j; + int k; + int val; + int profit; + int[] prev; + int[] curr; + int[] invest; + int[] profits; + int[][] ans; + int[][] companies; + StringBuilder sb; + BufferedReader br; + StringTokenizer st; + + br = new BufferedReader(new InputStreamReader(System.in)); + st = new StringTokenizer(br.readLine(), " ", false); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + companies = new int[m][n + 1]; // 각 기업, 투자 액수별 이익금 + curr = new int[n + 1]; // 현재 DP 값 + ans = new int[m][n + 1]; // 상태별 마지막 투자 액수 + invest = ans[0]; // 첫 기업 투자 액수 + for (i = 1; i <= n; i++) { + st = new StringTokenizer(br.readLine(), " ", false); + st.nextToken(); + for (j = m - 1; j > 0; j--) { // 마지막 출력 시 거꾸로 추적하므로 기업 순서 뒤집기 + companies[j][i] = Integer.parseInt(st.nextToken()); + } + curr[i] = Integer.parseInt(st.nextToken()); // 마지막 기업은 DP 값으로 바로 적용 + invest[i] = i; // 투자 액수 저장 + } + prev = new int[n + 1]; // 이전 DP 저장용 + for (i = 1; i < m; i++) { + System.arraycopy(curr, 1, prev, 1, n); // 이전 상태 업데이트 + profits = companies[i]; // i 번 기업의 투자 액수별 이익금 + invest = ans[i]; // i 번 기업까지 계산했을 때 마지막 투자 액수 + for (j = 1; j <= n; j++) { + profit = profits[j]; // i 번 기업의 투자 액수 j 에 대한 이익금 + for (k = j; k <= n; k++) { + val = prev[k - j] + profit; // 새로운 이익 계산 + if (val > curr[k]) { // 새로운 이익이 현재 DP 값보다 크면 + invest[k] = j; // 마지막 투자 액수 업데이트 + curr[k] = val; // DP 값 업데이트 + } + } + } + } + sb = new StringBuilder(); + sb.append(curr[n]).append(LINE_BREAK); // 최대 이익금 + j = n; + for (i = m - 1; i >= 0; i--) { // 기업 역추적 + sb.append(ans[i][j]).append(SPACE); // 해당 기업에 투자한 액수 출력 + j -= ans[i][j]; // 투자금 합 역추적 + } + System.out.print(sb.toString()); + } +} diff --git "a/junghyunwoo/4th/week5/BOJ31716_\355\230\204\353\214\200\353\252\250\353\271\204\354\212\244\354\236\220\354\234\250\354\243\274\355\226\211\355\205\214\354\212\244\355\214\2051.java" "b/junghyunwoo/4th/week5/BOJ31716_\355\230\204\353\214\200\353\252\250\353\271\204\354\212\244\354\236\220\354\234\250\354\243\274\355\226\211\355\205\214\354\212\244\355\214\2051.java" new file mode 100644 index 0000000..1e6a3cc --- /dev/null +++ "b/junghyunwoo/4th/week5/BOJ31716_\355\230\204\353\214\200\353\252\250\353\271\204\354\212\244\354\236\220\354\234\250\354\243\274\355\226\211\355\205\214\354\212\244\355\214\2051.java" @@ -0,0 +1,88 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +/** + * [BOJ] 현대모비스 자율 주행 테스팅 1 / Gold 3 / 15m + * - 84 ms + * - 그리디 + * - 시작 열에 장애물이 두 개면 완주 불가 + * - K > 1 이고, 시작 열과 도착 열에 + * - 대각으로 장애물이 있으면 완주 불가 + * - 첫 장애물 위치의 반대 차선으로 시작점 결정 + * - 첫 장애물 옆까지 직진 + * - 현재 차선 앞에 장애물이 없으면 직진 + * - 현재 차선 앞에 장애물이 존재하면 + * - 차선 변경할 위치, 이후 직진할 위치 중 장애물이 없으면 + * - 차선 변경 후 직진 + * - 둘 중 하나라도 장애물이 존재하면 완주 불가 + * - 도착 지점 차선과 시작 지점 차선이 같으면 + * - 직진하여 다음 샘플 주행 트랙으로 이동 + * - 도착 지점 차선과 시작 지점 차선이 다르면 + * - 직진 후 차선 변경 혹은 차선 변경 후 직진 + * - (샘플 주행 트랙 이동 * K) + * - + (트랙간 이동 * (K - 1)) 출력 + * */ +public class BOJ31716_현대모비스자율주행테스팅1 { + private static final char OBSTACLE = '#'; + private static final char[] FAIL = {'-', '1'}; + + public static void main(String[] args) throws IOException { + int n; + int i; + int cnt; + int add; + int lane; + int start; + long k; + char[][] map; + BufferedReader br; + StringTokenizer st; + + br = new BufferedReader(new InputStreamReader(System.in)); + st = new StringTokenizer(br.readLine(), " ", false); + n = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + map = new char[2][n]; + br.read(map[0], 0, n); + br.read(); + br.read(map[1], 0, n); + if ((map[0][0] == OBSTACLE && map[1][0] == OBSTACLE) || (k > 1 + && ((map[0][n - 1] == OBSTACLE && map[1][0] == OBSTACLE) + || (map[1][n - 1] == OBSTACLE && map[0][0] == OBSTACLE)))) { + System.out.print(FAIL); // 시작 열에 장애물이 두 개면 완주 불가 + return; // K > 1 이고, 시작 열과 도착 열에 대각으로 장애물이 있으면 완주 불가 + } + start = lane = 0; + for (i = 0; i < n; i++) { // 첫 장애물 위치의 반대 차선으로 시작점 결정 + if (map[0][i] == OBSTACLE) { + start = lane = 1; + break; + } else if (map[1][i] == OBSTACLE) { + start = lane = 0; + break; + } + } + if (i == n) { + i--; + } + cnt = i; // 첫 장애물 옆까지 직진 + for (++i; i < n; i++) { + if (map[lane][i] != OBSTACLE) { // 현재 차선 앞에 장애물이 없으면 + cnt++; // 직진 + } else if (map[lane ^= 1][i - 1] != OBSTACLE && map[lane][i] != OBSTACLE) { + cnt += 2; // 차선 변경할 위치, 이후 직진할 위치 중 장애물이 없으면 차선 변경 후 직진 + } else { // 둘 중 하나라도 장애물이 존재하면 + System.out.print(FAIL); // 완주 불가 + return; + } + } + if (lane == start) { // 도착 지점 차선과 시작 지점 차선이 같으면 + add = 1; // 직진하여 다음 샘플 주행 트랙으로 이동 + } else { // 도착 지점 차선과 시작 지점 차선이 다르면 + add = 2; // 직진 후 차선 변경 혹은 차선 변경 후 직진 + } // (샘플 주행 트랙 이동 * K) + (트랙간 이동 * (K - 1)) 출력 + System.out.print(cnt * k + add * (k - 1L)); + } +}