From 15673a851b0e407a4b5c31a47e1f2b99a7dc489f Mon Sep 17 00:00:00 2001 From: NavyHubb Date: Sun, 14 Jan 2024 18:57:48 +0900 Subject: [PATCH] 240114 --- ...\354\240\204\353\266\204\353\260\260.java" | 86 +++++++++++ "src/graph/BOJ_5427_\353\266\210.java" | 138 ++++++++++++++++++ ...\354\212\244\354\234\204\354\271\230.java" | 71 +++++++++ 3 files changed, 295 insertions(+) create mode 100644 "src/dp/BOJ_1943_\353\217\231\354\240\204\353\266\204\353\260\260.java" create mode 100644 "src/graph/BOJ_5427_\353\266\210.java" create mode 100644 "src/greedy/BOJ_2138_\354\240\204\352\265\254\354\231\200\354\212\244\354\234\204\354\271\230.java" diff --git "a/src/dp/BOJ_1943_\353\217\231\354\240\204\353\266\204\353\260\260.java" "b/src/dp/BOJ_1943_\353\217\231\354\240\204\353\266\204\353\260\260.java" new file mode 100644 index 0000000..69e41c4 --- /dev/null +++ "b/src/dp/BOJ_1943_\353\217\231\354\240\204\353\266\204\353\260\260.java" @@ -0,0 +1,86 @@ +package dp; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +/** + * [문제 분석] + * 세 개의 케이스가 주어진다 + * 동전의 크기와 갯수가 주어질 때, 전체 금액을 절반으로 나눌 수 있는지 판단하라 + * + * [문제 풀이] + * + */ +public class BOJ_1943_동전분배 { + + static int N, total; + static Coin[] coins; + static boolean[] dp; + static class Coin { + int value, quantity; + + public Coin(int value, int quantity) { + this.value = value; + this.quantity = quantity; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + + for (int t = 0; t < 3; t++) { + N = Integer.parseInt(br.readLine()); + coins = new Coin[N]; + total = 0; + dp = new boolean[100_001]; // 원장님이 주신 금액의 최댓값은 100,000원 + + for (int i = 0; i < N; i++) { + st = new StringTokenizer(br.readLine()); + int value = Integer.parseInt(st.nextToken()); + int quantity = Integer.parseInt(st.nextToken()); + + coins[i] = new Coin(value, quantity); + total += value * quantity; + + // 현재 동전으로 만들 수 있는 금액을 true 처리 + for (int j = 1; j <= quantity; j++) { + dp[value * j] = true; + } + } + + if (solution()) { + System.out.println(1); + } else { + System.out.println(0); + } + } + } + + private static boolean solution() { + if (total%2 != 0) { + return false; // 총액이 홀수인 경우 + } + if (dp[total/2]) { // 이미 반으로 나눌 수 있음이 확인된 경우 + return true; + } + + dp[0] = true; + for (Coin coin : coins) { + for (int i = total/2; i >= coin.value; i--) { + if (dp[i - coin.value]) { + for (int j = 1; j <= coin.quantity; j++) { + if ((i - coin.value) + (coin.value*j) > total/2) break; // total/2 이상으로는 탐색할 필요 없음 + + dp[(i - coin.value) + (coin.value*j)] = true; + } + } + } + } + + return dp[total/2]; + } + +} \ No newline at end of file diff --git "a/src/graph/BOJ_5427_\353\266\210.java" "b/src/graph/BOJ_5427_\353\266\210.java" new file mode 100644 index 0000000..02bcce4 --- /dev/null +++ "b/src/graph/BOJ_5427_\353\266\210.java" @@ -0,0 +1,138 @@ +package graph; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +/** + * [문제 분석] + * 건물의 일부에 불이 났고, 상근이는 출구를 향해 뛰고 있다 + * 매 초마다 불은 인접사방의 빈 공간으로 확산된다 + * 상근이는 벽을 통과할 수 없고, 불이 있는 칸, 이제 불이 있을 칸으로 이동할 수 없다 + * 얼마나 빨리 빌딩을 탈출할 수 있는지 구하라 + * + * [문제 풀이] + * + */ +public class BOJ_5427_불 { + + static int N, M; + static char[][] map; + static int[] di = {-1, 1, 0, 0}; + static int[] dj = {0, 0, -1, 1}; + static Queue fires; + static Queue people; + static class Point { + int i, j; + + public Point(int i, int j) { + this.i = i; + this.j = j; + } + } + static class Person { + int i, j, cnt; + + public Person(int i, int j, int cnt) { + this.i = i; + this.j = j; + this.cnt = cnt; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + + int T = Integer.parseInt(br.readLine()); + while (T-- > 0) { + st = new StringTokenizer(br.readLine()); + M = Integer.parseInt(st.nextToken()); + N = Integer.parseInt(st.nextToken()); + fires = new LinkedList<>(); + people = new LinkedList<>(); + + map = new char[N][M]; + for (int i = 0; i < N; i++) { + String str = br.readLine(); + for (int j = 0; j < M; j++) { + char ch = str.charAt(j); + if (ch == '@') { // 상근 + people.add(new Person(i, j, 0)); + } else if (ch == '*') { // 불 + fires.add(new Point(i, j)); + } + map[i][j] = ch; + } + } + + solution(); + } + } + + private static void solution() { + int result = -1; + while (true) { + // 불 확산 + spread(); + + // 상근 이동 + result = move(); + if (result != -1) break; + if (people.isEmpty()) break; + } + + if (result != -1) { + System.out.println(result); + } else { + System.out.println("IMPOSSIBLE"); + } + } + + private static int move() { + int size = people.size(); + for (int i = 0; i < size; i++) { + Person cur = people.poll(); + + for (int d = 0; d < 4; d++) { + int ni = cur.i + di[d]; + int nj = cur.j + dj[d]; + + if (ni < 0 || nj < 0 || ni >= N || nj >= M) { + return cur.cnt + 1; + } + + if (map[ni][nj] == '.') { + map[ni][nj] = '@'; + people.add(new Person(ni, nj, cur.cnt+1)); + } + } + } + + return -1; + } + + private static void spread() { + // 현재 저장되어 있는 불의 위치만큼만 수행 + int size = fires.size(); + for (int i = 0; i < size; i++) { + Point point = fires.poll(); + + for (int d = 0; d < 4; d++) { + int ni = point.i + di[d]; + int nj = point.j + dj[d]; + + if (ni < 0 || nj < 0 || ni >= N || nj >= M) continue; + + if (map[ni][nj] == '.' || map[ni][nj] == '@') { + map[ni][nj] = '*'; + fires.add(new Point(ni, nj)); + } + } + } + } + +} \ No newline at end of file diff --git "a/src/greedy/BOJ_2138_\354\240\204\352\265\254\354\231\200\354\212\244\354\234\204\354\271\230.java" "b/src/greedy/BOJ_2138_\354\240\204\352\265\254\354\231\200\354\212\244\354\234\204\354\271\230.java" new file mode 100644 index 0000000..d8257eb --- /dev/null +++ "b/src/greedy/BOJ_2138_\354\240\204\352\265\254\354\231\200\354\212\244\354\234\204\354\271\230.java" @@ -0,0 +1,71 @@ +package greedy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class BOJ_2138_전구와스위치 { + + static final int INF = Integer.MAX_VALUE; + static int N; + static boolean[] now_on, goal, now_off; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + N = Integer.parseInt(br.readLine()); + String str1 = br.readLine(); + String str2 = br.readLine(); + + now_on = new boolean[N]; + now_off = new boolean[N]; + goal = new boolean[N]; + + int cnt_on = 1, cnt_off = 0; // 스위치를 켜는 경우의 누른 횟수와 끄는 경우의 누른 횟수 + + for (int i = 0; i < N; i++) { + now_on[i] = str1.charAt(i) == '1' ? true : false; + now_off[i] = now_on[i]; + goal[i] = str2.charAt(i) == '1' ? true : false; + } + + // 첫번째 스위치를 켜는 경우: 첫번째 전구와 두번째 전구가 상태가 바뀐다 + now_on[0] = !now_on[0]; + now_on[1] = !now_on[1]; + + // 두번째 스위치부터 탐색 + for (int i = 1; i < N; i++) { + if (now_on[i-1] != goal[i-1]) { // 현재 스위치의 위치의 좌측 전구의 상태가 목표 상태와 다르다면 + // 현재 스위치 on + now_on[i-1] = !now_on[i-1]; + now_on[i] = !now_on[i]; + if (i < N-1) { // 마지막 스위치가 아닌 경우에만 i+1 전구에 접근. ArrayOutOfIndex 방지 + now_on[i+1] = !now_on[i+1]; + } + + cnt_on++; + } + + if (now_off[i-1] != goal[i-1]) { // 현재 스위치의 위치의 좌측 전구의 상태가 목표 상태와 다르다면 + // 현재 스위치 on + now_off[i-1] = !now_off[i-1]; + now_off[i] = !now_off[i]; + if (i < N-1) { // 마지막 스위치가 아닌 경우에만 i+1 전구에 접근. ArrayOutOfIndex 방지 + now_off[i+1] = !now_off[i+1]; + } + + cnt_off++; + } + } + + if (now_on[N-1] != goal[N-1]) cnt_on = INF; + if (now_off[N-1] != goal[N-1]) cnt_off = INF; + + if (cnt_on == INF && cnt_off == INF) { + System.out.println(-1); + } else { + System.out.println(Math.min(cnt_on, cnt_off)); + } + } + +}