diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..e8a9d98 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + 1731824086941 + + + + \ No newline at end of file diff --git a/week5/KCW/W5_1194.java b/week5/KCW/W5_1194.java new file mode 100644 index 0000000..5c9224c --- /dev/null +++ b/week5/KCW/W5_1194.java @@ -0,0 +1,116 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +//1194 달이 차오른다, 가자. +/* +조건 1. 빈칸은 언제나 이동 가능, 벽은 절대 이동 불가능 +조건 2. 열쇠가 있을 때만 문을 지날 수 있음 +조건 3. 출구는 한 개가 아님 +조건 4. 같은 열쇠나 문이 여러 번 나올 수 있음, 문에 대응하는 열쇠가 없을 수도 있음 +조건 5. 열쇠는 여러 번 사용할 수 있음 + +사용 방법 : BFS -> 메모리초과 +대안 : visited배열과 hasKey 배열을 비트마스킹 방법으로 표현 -> 메모리초과 +대안 : hasKey 숫자가 여러 배리에이션으로 다양해졌으니 visited 배열을 전역변수로 두고 관리 +-> 다음의 과정으로 풀 수 있었음 + */ +public class Main { + static int n, m; + static int[] dx = {0, 0, -1, 1}; + static int[] dy = {-1, 1, 0, 0}; + static Character[][] map; + static boolean[][][] visited; + + static class Stat { + int x, y, depth, hasKey; + + Stat(int x, int y, int depth, int hasKey) { + this.x = x; + this.y = y; + this.depth = depth; + this.hasKey = hasKey; + } + + boolean unlocked(char ch) { + return (hasKey & (1 << (ch - 'A'))) != 0; //0100가 반환된다면 이 값은 4임 + } + } + + static int bfs(int x, int y) { + Queue q = new LinkedList<>(); + boolean[][][] visited = new boolean[n][m][1 << 6]; //6은 열쇠 개수 + q.add(new Stat(x, y, 1, 0)); + visited[y][x][0] = true; + + while (!q.isEmpty()) { + Stat p = q.poll(); + + for (int i = 0; i < 4; i++) { + int nx = p.x + dx[i]; + int ny = p.y + dy[i]; + + // 경계 조건 & 벽이거나 & 방문한 적 있으면 continue + if (nx < 0 || ny < 0 || nx >= m || ny >= n || map[ny][nx] == '#' || visited[ny][nx][p.hasKey]) continue; + + if (map[ny][nx] == '1') { + return p.depth; + } + + // 열쇠를 줍는 경우 + if (map[ny][nx] >= 'a' && map[ny][nx] <= 'f') { + int keyIdx = 1 << (map[ny][nx] - 'a'); + //열쇠가 이미 있는 경우 + if((p.hasKey & keyIdx) == keyIdx ){ + visited[ny][nx][p.hasKey] = true; + q.add(new Stat(nx, ny, p.depth + 1, p.hasKey)); + } else{ //열쇠를 처음 얻는 경우 + int newHasKey = p.hasKey | keyIdx; // 복사본 생성 + visited[ny][nx][newHasKey] = true; + visited[ny][nx][p.hasKey] = true; + + q.add(new Stat(nx, ny, p.depth + 1, newHasKey)); + } + } + // 문인 경우 + if (map[ny][nx] >= 'A' && map[ny][nx] <= 'F' && p.unlocked(map[ny][nx])) { + visited[ny][nx][p.hasKey] = true; + q.add(new Stat(nx, ny, p.depth + 1, p.hasKey)); + } + + // 열쇠 없을 때 이동 + if (map[ny][nx] == '.') { + visited[ny][nx][p.hasKey] = true; + q.add(new Stat(nx, ny, p.depth + 1, p.hasKey)); + } + } + } + + return -1; + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + map = new Character[n][m]; + int x = 0, y = 0; + for (int i = 0; i < n; i++) { + String str = br.readLine(); + for (int j = 0; j < m; j++) { + map[i][j] = str.charAt(j); + if (str.charAt(j) == '0') { + x = j; + y = i; + map[i][j] = '.'; + } + } + } + + System.out.println(bfs(x, y)); + } +} diff --git a/week5/KCW/W5_13458.java b/week5/KCW/W5_13458.java new file mode 100644 index 0000000..a668656 --- /dev/null +++ b/week5/KCW/W5_13458.java @@ -0,0 +1,36 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; +//13458 시험 감독 +public class Main { + static int N, B, C; + static int[] arr; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + N = Integer.parseInt(br.readLine()); + arr = new int[N]; + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < N; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + st = new StringTokenizer(br.readLine()); + B = Integer.parseInt(st.nextToken()); + C = Integer.parseInt(st.nextToken()); + + long cnt = 0; + for (int i = 0; i < N; i++) { + cnt += 1; + if (arr[i] <= B) { + continue; + } + double viewers = (double) (arr[i] - B) / C; + if ((viewers * 10) % 10 > 0)//올림을 위해 소수점 검사 + cnt += 1; + cnt += (arr[i] - B) / C; + } + System.out.println(cnt); + } +} diff --git a/week5/KCW/W5_16236.java b/week5/KCW/W5_16236.java new file mode 100644 index 0000000..98ecba5 --- /dev/null +++ b/week5/KCW/W5_16236.java @@ -0,0 +1,135 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; +//16236 아기상어 +/* +fish 클래스 +findFish 함수(int x, int y, int size) +먹는 기작은 다음과 같다. +1. find로 가장 가까운 fish를 찾는다. +2. 아기상어의 크기, x, y를 바꾸고 결과값을 저장한다 +3. 1번부터 반복한다. + +find 함수 +1. 아기상어보다 큰 물고기는 벽이다. 지나갈 수 없다. +2. 자신의 크기와 같은 수의 물고기를 먹을 때 마다 크기가 1 증가한다. +3. 크기가 같은 물고기는 먹을 수 없지만, 그 물고기가 있는 칸은 지나갈 수 있다. + */ +public class Main { + static int n; + static int[][] map; + + static class Fish implements Comparable { + int x, y, size, depth; + + Fish(int x, int y, int size, int depth) { + this.x = x; + this.y = y; + this.size = size; + this.depth = depth; + } + + @Override + public int compareTo(Fish o) { + if (depth == o.depth) { + if (y == o.y) { + return x - o.x; + } + return y - o.y; //위에 있어야 함, 0과 2가 있을 때 0 - 2 음수 그대로 + } + return depth - o.depth;//음수가 나오면 맞는 방향, 양수가 나오면 방향을 바꿔줌 + } + } + + static class LittleShark extends Fish { + int ateFish; + LittleShark(int x, int y, int size, int depth) { + super(x, y, size, depth); + ateFish = 0; + } + + public void eat(Fish fish){ + x = fish.x; + y = fish.y; + depth += fish.depth; + ateFish++; + if(ateFish == size) { + size++; + ateFish = 0; + } + map[y][x] = 0; + } + } + + static Fish find(Fish littleShark) { + int[] dx = {0, 0, -1, 1}; + int[] dy = {1, -1, 0, 0}; + boolean[][] visited = new boolean[n][n]; + int[][] fishMap = new int[n][n]; + for (int i = 0; i < n; i++) { + fishMap[i] = map[i].clone(); // 깊은 복사 + } + Queue q = new LinkedList<>(); + ArrayList fishes = new ArrayList<>(); + + q.add(littleShark); + visited[littleShark.y][littleShark.x] = true; + + while (!q.isEmpty()) { + Fish fish = q.poll(); + + for (int i = 0; i < 4; i++) { + int nx = fish.x + dx[i]; + int ny = fish.y + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= n || visited[ny][nx]) continue; + + if (fishMap[ny][nx] == 0 || fishMap[ny][nx] == littleShark.size) { + //물고기가 없거나 물고기가 아기상어와 같은 크기일 때 지나서 감 + visited[ny][nx] = true; + q.add(new Fish(nx, ny, fish.size, fish.depth + 1)); + } else if (fishMap[ny][nx] > littleShark.size) { + visited[ny][nx] = true; + //물고기가 아기상어보다 클 때 : 돌아서 감, 아무것도 큐에 넣지 않음 + } else if (fishMap[ny][nx] < littleShark.size) { + //아기상어가 먹을 수 있는 물고기일 때 : 먹을 수 있는 후보에 들어감 + visited[ny][nx] = true; + fishes.add(new Fish(nx, ny, fishMap[ny][nx], fish.depth + 1)); + fishMap[ny][nx] = 0; + } + } + } + + if (fishes.isEmpty()) return null; + Collections.sort(fishes); + return fishes.get(0); + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + n = Integer.parseInt(br.readLine()); + map = new int[n][n]; + LittleShark littleShark = null; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + map[i][j] = Integer.parseInt(st.nextToken()); + if (map[i][j] == 9) { + littleShark = new LittleShark(j, i, 2, 0); + map[i][j] = 0; + } + } + } + + Fish foodFish = find(littleShark); + while (foodFish != null) { + littleShark.eat(foodFish); + Fish newLittleShark = new Fish(littleShark.x, littleShark.y, littleShark.size, 0); + foodFish = find(newLittleShark); + } + + System.out.println(littleShark.depth); + } +} diff --git a/week5/KCW/W5_2206.java b/week5/KCW/W5_2206.java new file mode 100644 index 0000000..2e1f687 --- /dev/null +++ b/week5/KCW/W5_2206.java @@ -0,0 +1,81 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +//2206 벽 부수고 이동하기 +public class Main { + static int n, m; + static int[] dx = {0, 0, -1, 1}; + static int[] dy = {-1, 1, 0, 0}; + static int[][] map; + static boolean[][][] visited; + + static class Point { + int x, y, depth; + boolean hasBroken; + + Point(int x, int y, int depth, boolean hasBroken) { + this.x = x; + this.y = y; + this.depth = depth; + this.hasBroken = hasBroken; + } + } + + static int bfs() { + Queue q = new LinkedList<>(); + q.add(new Point(0, 0, 1, false)); + visited[0][0][0] = true; + + while (!q.isEmpty()) { + Point p = q.poll(); + + if (p.x == n - 1 & p.y == m - 1) { + return p.depth; + } + + for (int i = 0; i < 4; i++) { + int nx = p.x + dx[i]; + int ny = p.y + dy[i]; + + // 경계 조건 + if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue; + + // 벽을 부순 적이 없는 경우 + if (map[nx][ny] == 1 && !p.hasBroken && !visited[nx][ny][1]) { + visited[nx][ny][1] = true; + q.add(new Point(nx, ny, p.depth + 1, true)); + } + + // 일반적인 이동 + if (map[nx][ny] == 0 && !visited[nx][ny][p.hasBroken ? 1 : 0]) { + visited[nx][ny][p.hasBroken ? 1 : 0] = true; + q.add(new Point(nx, ny, p.depth + 1, p.hasBroken)); + } + } + } + + return -1; + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + map = new int[n][m]; + visited = new boolean[n][m][2]; + + for (int i = 0; i < n; i++) { + String str = br.readLine(); + for (int j = 0; j < m; j++) { + map[i][j] = str.charAt(j) - '0'; + } + } + + System.out.println(bfs()); + } +} diff --git a/week5/KCW/start.txt b/week5/KCW/start.txt deleted file mode 100644 index 945c9b4..0000000 --- a/week5/KCW/start.txt +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file