From 0bf429757c721ec270f9e8c2229504274ac3cdd7 Mon Sep 17 00:00:00 2001 From: JeeIn Lee Date: Sun, 6 Aug 2023 14:55:54 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=80merge:=20[Week22~23]=20MST=203?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20+=20Simulation=202=EB=AC=B8=EC=A0=9C=20(#8?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨feat: MST 알고리즘 풀이 * ✨feat: 시뮬레이션 알고리즘 풀이 --- ...353\213\235_\355\212\270\353\246\254.java" | 81 ++++++++++++++++ ...355\201\254_\354\227\260\352\262\260.java" | 84 +++++++++++++++++ ...354\213\234_\352\261\264\354\204\244.java" | 93 +++++++++++++++++++ ...\354\262\234\355\225\230\352\270\260.java" | 81 ++++++++++++++++ ...\354\230\250\353\202\234\355\231\224.java" | 81 ++++++++++++++++ 5 files changed, 420 insertions(+) create mode 100644 "jinny-l/week_22/BOJ_1197_\354\265\234\354\206\214_\354\212\244\355\214\250\353\213\235_\355\212\270\353\246\254.java" create mode 100644 "jinny-l/week_22/BOJ_1922_\353\204\244\355\212\270\354\233\214\355\201\254_\354\227\260\352\262\260.java" create mode 100644 "jinny-l/week_22/BOJ_21924_\353\217\204\354\213\234_\352\261\264\354\204\244.java" create mode 100644 "jinny-l/week_23/BOJ_1713_\355\233\204\353\263\264_\354\266\224\354\262\234\355\225\230\352\270\260.java" create mode 100644 "jinny-l/week_23/BOJ_5212_\354\247\200\352\265\254_\354\230\250\353\202\234\355\231\224.java" diff --git "a/jinny-l/week_22/BOJ_1197_\354\265\234\354\206\214_\354\212\244\355\214\250\353\213\235_\355\212\270\353\246\254.java" "b/jinny-l/week_22/BOJ_1197_\354\265\234\354\206\214_\354\212\244\355\214\250\353\213\235_\355\212\270\353\246\254.java" new file mode 100644 index 0000000..3483236 --- /dev/null +++ "b/jinny-l/week_22/BOJ_1197_\354\265\234\354\206\214_\354\212\244\355\214\250\353\213\235_\355\212\270\353\246\254.java" @@ -0,0 +1,81 @@ +package week_22; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Comparator; +import java.util.StringTokenizer; + +public class BOJ_1197_최소_스패닝_트리 { + + private static int[] parents; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine(), " "); + + // 입력 + int vertexCnt = Integer.parseInt(st.nextToken()); + int edgeCnt = Integer.parseInt(st.nextToken()); + + Vertex[] trees = new Vertex[edgeCnt]; + for (int i = 0; i < edgeCnt; i++) { + st = new StringTokenizer(br.readLine(), " "); + Vertex vertex = new Vertex(); + vertex.start = Integer.parseInt(st.nextToken()); + vertex.end = Integer.parseInt(st.nextToken()); + vertex.cost = Integer.parseInt(st.nextToken()); + trees[i] = vertex; + } + + // 가중치 기준 정렬 + Arrays.sort(trees, (Comparator.comparingLong(o -> o.cost))); + + // 부모 노드 초기화 + parents = new int[vertexCnt + 1]; + for (int i = 0; i <= vertexCnt; i++) { + parents[i] = i; + } + + // 크루스칼 알고리즘 + int sum = 0; + for (int i = 0; i < edgeCnt; i++) { + Vertex vertex = trees[i]; + int start = vertex.start; + int end = vertex.end; + + if (!sameParent(start, end)) { // 사이클이 형성되지 않으면 + union(start, end); // 부모 노드를 바꿔주고 + sum += vertex.cost; // 가중치 더해주기 + } + } + + System.out.println(sum); + } + + static class Vertex { + int start; + int end; + long cost; + } + + private static void union(int a, int b) { + if (find(a) > find(b)) { + parents[find(a)] = find(b); + } else { + parents[find(b)] = find(a); + } + } + + private static int find(int a) { + if (parents[a] == a) { + return a; + } + return parents[a] = find(parents[a]); // ??? + } + + private static boolean sameParent(int x, int y) { + return find(x) == find(y); + } +} diff --git "a/jinny-l/week_22/BOJ_1922_\353\204\244\355\212\270\354\233\214\355\201\254_\354\227\260\352\262\260.java" "b/jinny-l/week_22/BOJ_1922_\353\204\244\355\212\270\354\233\214\355\201\254_\354\227\260\352\262\260.java" new file mode 100644 index 0000000..cb80dfa --- /dev/null +++ "b/jinny-l/week_22/BOJ_1922_\353\204\244\355\212\270\354\233\214\355\201\254_\354\227\260\352\262\260.java" @@ -0,0 +1,84 @@ +package week_22; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Comparator; +import java.util.StringTokenizer; + +public class BOJ_1922_네트워크_연결 { + + private static int[] parents; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // 입력 + int vertexCnt = Integer.parseInt(br.readLine()); + int edgeCnt = Integer.parseInt(br.readLine()); + + Vertex[] trees = new Vertex[edgeCnt]; + for (int i = 0; i < edgeCnt; i++) { + StringTokenizer st = new StringTokenizer(br.readLine(), " "); + Vertex vertex = new Vertex(); + + vertex.start = Integer.parseInt(st.nextToken()); + vertex.end = Integer.parseInt(st.nextToken()); + vertex.cost = Integer.parseInt(st.nextToken()); + + trees[i] = vertex; + } + // 정렬 + Arrays.sort(trees, Comparator.comparingInt(o -> o.cost)); + + // 부모 노드 초기화 + parents = new int[vertexCnt + 1]; + for (int i = 0; i <= vertexCnt; i++) { + parents[i] = i; + } + + // 크루스칼 알고리즘 + int cost = 0; + for (int i = 0; i < edgeCnt; i++) { + Vertex vertex = trees[i]; + int start = vertex.start; + int end = vertex.end; + + if (!sameParent(start, end)) { + union(start, end); + cost += vertex.cost; + } + } + System.out.println(cost); + } + + static class Vertex { + int start; + int end; + int cost; + } + + private static boolean sameParent(int x, int y) { + return find(x) == find(y); + } + + private static int find(int vertex) { + if (parents[vertex] == vertex) { // 여기도 왜 자기 자신일 떄는 그냥 돌아가는지 모르겠음 + return vertex; + } + return parents[vertex] = find(parents[vertex]); // 여기 이해 못함 + } + + private static void union(int x, int y) { + int xParent = find(x); + int yParent = find(y); + + if (xParent > yParent) { + parents[x] = yParent; // 여기 잘못됨 + } else { + parents[y] = xParent; + } + } + +} diff --git "a/jinny-l/week_22/BOJ_21924_\353\217\204\354\213\234_\352\261\264\354\204\244.java" "b/jinny-l/week_22/BOJ_21924_\353\217\204\354\213\234_\352\261\264\354\204\244.java" new file mode 100644 index 0000000..b23a33b --- /dev/null +++ "b/jinny-l/week_22/BOJ_21924_\353\217\204\354\213\234_\352\261\264\354\204\244.java" @@ -0,0 +1,93 @@ +package week_22; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Comparator; +import java.util.StringTokenizer; + +// TODO: 이해가 가지 않는 점: union find 하면서 부모 노드가 다 똑같이 변해야 하는 게 아닌가? 왜 2번 예저는 부모 노드가 다르지???? +// TODO: 이상한 입력 조건 머냐 저거,, ㅎ + +public class BOJ_21924_도시_건설 { + + private static int[] parents; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine(), " "); + + // 입력 + int vertexCnt = Integer.parseInt(st.nextToken()); + int edgeCnt = Integer.parseInt(st.nextToken()); + + long totalCost = 0; + Vertex[] trees = new Vertex[edgeCnt]; + for (int i = 0; i < edgeCnt; i++) { + st = new StringTokenizer(br.readLine(), " "); + Vertex vertex = new Vertex(); + + vertex.start = Integer.parseInt(st.nextToken()); + vertex.end = Integer.parseInt(st.nextToken()); + vertex.cost = Integer.parseInt(st.nextToken()); + + trees[i] = vertex; + totalCost += vertex.cost; + } + + // 가중치 기준 정렬 + Arrays.sort(trees, (Comparator.comparingInt(o -> o.cost))); + + // 부모 노드 초기화 + parents = new int[vertexCnt + 1]; + for (int i = 0; i <= vertexCnt; i++) { + parents[i] = i; + } + + // 크루스칼 알고리즘 + long minCost = 0; + int unionCnt = 0; + for (int i = 0; i < edgeCnt; i++) { + Vertex vertex = trees[i]; + int start = vertex.start; + int end = vertex.end; + + if (!sameParent(start, end)) { + union(start, end); + minCost += vertex.cost; + unionCnt++; + } + } + if (unionCnt != vertexCnt - 1) { + System.out.println(-1); + return; + } + System.out.println(totalCost - minCost); + } + + static class Vertex { + int start; + int end; + int cost; + } + + private static void union(int a, int b) { + if (find(a) > find(b)) { + parents[find(a)] = find(b); + } else { + parents[find(b)] = find(a); + } + } + + private static int find(int a) { + if (parents[a] == a) { + return a; + } + return parents[a] = find(parents[a]); // 이런 문법 처음봄,, + } + + private static boolean sameParent(int x, int y) { + return find(x) == find(y); + } +} diff --git "a/jinny-l/week_23/BOJ_1713_\355\233\204\353\263\264_\354\266\224\354\262\234\355\225\230\352\270\260.java" "b/jinny-l/week_23/BOJ_1713_\355\233\204\353\263\264_\354\266\224\354\262\234\355\225\230\352\270\260.java" new file mode 100644 index 0000000..08d6e9d --- /dev/null +++ "b/jinny-l/week_23/BOJ_1713_\355\233\204\353\263\264_\354\266\224\354\262\234\355\225\230\352\270\260.java" @@ -0,0 +1,81 @@ +package week_23; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.StringTokenizer; + +public class BOJ_1713_후보_추천하기 { + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // 입력 + int postSize = Integer.parseInt(br.readLine()); + int votes = Integer.parseInt(br.readLine()); + StringTokenizer st = new StringTokenizer(br.readLine(), " "); + + // 최종 후보 확인 + Student[] students = new Student[101]; // 모든 학생의 정보를 담는 배열 + List post = new ArrayList<>(); // 사진틀에 게시된 최종 후보의 학생 정보를 담는 배열 + + for (int i = 0; i < votes; i++) { + int vote = Integer.parseInt(st.nextToken()); + + if (students[vote] == null) { // 처음 추천받았다면 객체 생성 + students[vote] = new Student(vote, 0, 0, false); + } + + if (students[vote].isPosted) { // 이미 게시되어 있으면 추천수만 1증가 + students[vote].count++; // 4번 조건 주의 + continue; + } + + if (post.size() < postSize) { // 사진틀이 비어있으면 + post.add(students[vote]); // 게시하고 + + } else { // 사진들이 차있으면 + Collections.sort(post); // 추천순, 시간순으로 정렬하고 + post.get(0).isPosted = false; // 게시 여부 정보 바꾸고 + post.get(0).count = 0; // 추천 수 0으로 변경 + post.remove(0); // 기존 학생 제거하고 + post.add(students[vote]); // 새로운 학생 게시 + } + + // 추천된 학생 정보 업데이트 + students[vote].count++; // 추천수 1 증가하고 + students[vote].time = i; // 포스팅 시간 업데이트하고 + students[vote].isPosted = true; // 포스팅 여부 업데이트 + } + + // 출력 + post.sort(Comparator.comparingInt(o -> o.index)); + post.forEach(student -> System.out.print(student.index + " ")); + } + + static class Student implements Comparable { + int index; + int count; + int time; + boolean isPosted; + + public Student(int index, int count, int time, boolean isPosted) { + this.index = index; + this.count = count; + this.time = time; + this.isPosted = isPosted; + } + + @Override + public int compareTo(Student o) { + if (this.count == o.count) { + return this.time - o.time; + } + return this.count - o.count; + } + } +} diff --git "a/jinny-l/week_23/BOJ_5212_\354\247\200\352\265\254_\354\230\250\353\202\234\355\231\224.java" "b/jinny-l/week_23/BOJ_5212_\354\247\200\352\265\254_\354\230\250\353\202\234\355\231\224.java" new file mode 100644 index 0000000..62429e1 --- /dev/null +++ "b/jinny-l/week_23/BOJ_5212_\354\247\200\352\265\254_\354\230\250\353\202\234\355\231\224.java" @@ -0,0 +1,81 @@ +package week_23; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class BOJ_5212_지구_온난화 { + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine(), " "); + + // 입력 + int row = Integer.parseInt(st.nextToken()); + int column = Integer.parseInt(st.nextToken()); + + char[][] map = new char[row][column]; + for (int i = 0; i < row; i++) { + map[i] = br.readLine().toCharArray(); + } + + // 상, 하, 좌, 우 + int[] dx = {-1, 1, 0, 0}; + int[] dy = {0, 0, -1, 1}; + + // 지도 출력 범위 + int minRow = 10; + int minColumn = 10; + + int maxRow = 0; + int maxColumn = 0; + + // 섬 주위 3면 이상이 바다인지 체크 + char[][] newMap = new char[row][column]; + for (int i = 0; i < row; i++) { + for (int j = 0; j < column; j++) { + + if (map[i][j] == 'X') { // 땅인 경우 4방향 탐색 + int sea = 0; + + for (int k = 0; k < 4; k++) { + int x = dx[k] + i; + int y = dy[k] + j; + + // 지도 범위를 벗어났는지 확인, 벗어나면 바다 + if (x < 0 || y < 0 || x >= row || y >= column || map[x][y] == '.') { + sea++; + } + } + + if (sea < 3) { // 땅 주위 3면 이하가 바다면 땅 -> 땅 유지 + newMap[i][j] = 'X'; + + // 섬을 포함한 최소 크기의 지도를 출력하기 위해 지도 범위 변경 + minRow = Math.min(minRow, i); + minColumn = Math.min(minColumn, j); + + maxRow = Math.max(maxRow, i); + maxColumn = Math.max(maxColumn, j); + } else { + newMap[i][j] = '.'; + } + } else { // 바다면 바다 값 넣어주기 + newMap[i][j] = '.'; + } + } + } + + // 출력 + StringBuilder sb = new StringBuilder(); + for (int i = minRow; i <= maxRow; i++) { + for (int j = minColumn; j <= maxColumn; j++) { + sb.append(newMap[i][j]); + } + sb.append("\n"); + } + + System.out.print(sb); + } +}