From 8a310abd5794406fbd9696745fa65dcadd225e72 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 23 Jul 2022 10:22:09 +0900 Subject: [PATCH 001/163] =?UTF-8?q?[BOJ-20040-JAVA]=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=ED=81=B4=20=EA=B2=8C=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_20040.java | 101 +++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_20040.java diff --git a/java/BOJ/Gold/IV/G4_20040.java b/java/BOJ/Gold/IV/G4_20040.java new file mode 100644 index 0000000..df26006 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_20040.java @@ -0,0 +1,101 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/20040 + * + * ! 제목: 사이클 게임 + * ! 시간 제한: 1초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 사이클 게임은 두 명의 플레이어가 차례대로 돌아가며 진행하는 게임으로, 선 플레이어가 홀수 번째 차례를, 후 플레이어가 짝수 번째 차례를 진행한다. 게임 시작 시 0 부터 n − 1 까지 고유한 번호가 부여된 평면 상의 점 n 개가 주어지며, 이 중 어느 세 점도 일직선 위에 놓이지 않는다. 매 차례 마다 플레이어는 두 점을 선택해서 이를 연결하는 선분을 긋는데, 이전에 그린 선분을 다시 그을 수는 없지만 이미 그린 다른 선분과 교차하는 것은 가능하다. 게임을 진행하다가 처음으로 사이클을 완성하는 순간 게임이 종료된다. 사이클 C는 플레이어가 그린 선분들의 부분집합으로, 다음 조건을 만족한다. + * C에 속한 임의의 선분의 한 끝점에서 출발하여 모든 선분을 한 번씩만 지나서 출발점으로 되돌아올 수 있다. + * 문제는 선분을 여러 개 그리다 보면 사이클이 완성 되었는지의 여부를 판단하기 어려워 이미 사이클이 완성되었음에도 불구하고 게임을 계속 진행하게 될 수 있다는 것이다. 이 문제를 해결하기 위해서 게임의 진행 상황이 주어지면 몇 번째 차례에서 사이클이 완성되었는지, 혹은 아직 게임이 진행 중인지를 판단하는 프로그램을 작성하려 한다. + * 입력으로 점의 개수 n과 m 번째 차례까지의 게임 진행 상황이 주어지면 사이클이 완성 되었는지를 판단하고, 완성되었다면 몇 번째 차례에서 처음으로 사이클이 완성된 것인지를 출력하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 입력은 표준입력을 사용한다. 입력의 첫 번째 줄에는 점의 개수를 나타내는 정수 3 ≤ n ≤ 500,000 과 진행된 차례의 수를 나타내는 정수 3 ≤ m ≤ 1,000,000 이 주어진다. 게임에서 사용하는 n개의 점에는 0 부터 n − 1 까지 고유한 번호가 부여되어 있으며, 이 중 어느 세 점도 일직선 위에 놓이지 않는다. 이어지는 m 개의 입력 줄에는 각각 i번째 차례에 해당 플레이어가 선택한 두 점의 번호가 주어진다 (1 ≤ i ≤ m). + * + * 6 5 -> n m + * 0 1 -> a b + * 1 2 -> a b + * 1 3 -> a b + * 0 3 -> a b + * 4 5 -> a b + * + * ! 출력 + * 출력은 표준출력을 사용한다. 입력으로 주어진 케이스에 대해, m 번째 차례까지 게임을 진행한 상황에서 이미 게임이 종료되었다면 사이클이 처음으로 만들어진 차례의 번호를 양의 정수로 출력하고, m 번의 차례를 모두 처리한 이후에도 종료되지 않았다면 0을 출력한다. + * + * 4 + * + * ? 채점결과 + * 시간: 648ms + * 메모리: 136524KB + * 언어: JAVA8 +*/ +package Gold.IV; + +import java.io.*; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G4_20040 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 초기설정 + static int n, m, parent[]; + + // * 메인 + public static void main(String[] args) throws IOException { + int result = solution(); // ! 입력값 받으면서 바로 KRUSKAL 알고리즘 수행 + bw.write(String.valueOf(result)); // 출력 + + // * 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // * UNION_FIND + public static boolean union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a == b) { + return false; + } else if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + return true; + } + + // * UNION_FIND(합집합요소찾기) + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + // * 입력값받는 동시에 크루스칼(Kruskal) 알고리즘 수행 + public static int solution() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + parent = IntStream.range(0, n).toArray(); + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + if (!union(a, b)) { + return i+1; + } + } + return 0; + } +} From 0b3aecdb5cf5cfe0224e0e29a76e9ba0dfdf9134 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 23 Jul 2022 12:05:54 +0900 Subject: [PATCH 002/163] =?UTF-8?q?[BOJ-1202-JAVA]=20=EB=B3=B4=EC=84=9D=20?= =?UTF-8?q?=EB=8F=84=EB=91=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_1202.java | 112 ++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_1202.java diff --git a/java/BOJ/Gold/II/G2_1202.java b/java/BOJ/Gold/II/G2_1202.java new file mode 100644 index 0000000..82c44d3 --- /dev/null +++ b/java/BOJ/Gold/II/G2_1202.java @@ -0,0 +1,112 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/1202 + * + * ! 제목: 보석 도둑 + * ! 시간 제한: 1초 + * ! 메모리 제한: 256MB + * + * ! 문제 + * 세계적인 도둑 상덕이는 보석점을 털기로 결심했다. + * 상덕이가 털 보석점에는 보석이 총 N개 있다. 각 보석은 무게 Mi와 가격 Vi를 가지고 있다. 상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 Ci이다. 가방에는 최대 한 개의 보석만 넣을 수 있다. + * 상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000) + * 다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000) + * 다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci ≤ 100,000,000) + * 모든 숫자는 양의 정수이다. + * + * 3 2 -> n m + * 1 65 -> jewels.get(0) + * 5 23 -> ... + * 2 99 -> jewels.get(n-1) + * 10 -> bags.get(0) + * 2 -> bags.get(m-1) + * + * ! 출력 + * 첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다. + * + * 164 + * + * ? 채점 결과 + * 시간: 1760ms + * 메모리: 155316KB + * 언어: JAVA8 +*/ +package Gold.II; + +import java.io.*; +import java.util.ArrayList; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +public class G2_1202 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n; + static int m; + static ArrayList jewels = new ArrayList<>(); + static ArrayList bags = new ArrayList<>(); + static long weight = 0L; + + public static void main(String[] args) throws IOException { + input(); // 입력 받기 + steal(); // 보석 훔치기 + bw.write(String.valueOf(weight)); // 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // * 보석 훔치기 + public static void steal() { + int idx = 0; // 무게가 작은 순서의 보석대로 + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); // 훔칠 수 있는 보석들 + + // 최대로 담을 수 있는 무게가 작은 가방 순서대로 + for (int i = 0; i < m; i++) { + + int limitWeight = bags.get(i); + + // ! 현재 가방에서 훔칠 수 있는 보석들을 최대힙(pq)에 모두 담음 + // ! => 다음의 가방에서도 해당 보석을 모두 담을 수 있다. + // ! => 그 중에 가치가 제일 높은 보석을 우선으로 챙김(Greedy) + while (idx < n && jewels.get(idx)[0] <= limitWeight) { + pq.add(jewels.get(idx)[1]); + idx++; + } + + if (!pq.isEmpty()) { + weight += pq.poll(); + } + } + } + + // * 입력받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + jewels.add(new int[] {a, b}); + } + + jewels.sort((a, b) -> a[0] - b[0]); + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + bags.add(Integer.parseInt(st.nextToken())); + } + + bags.sort((a, b) -> a - b); + } +} From a4576389cccb25b8d8eef1d66e189340db48d510 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sun, 24 Jul 2022 19:12:59 +0900 Subject: [PATCH 003/163] =?UTF-8?q?[BOJ-10775-JAVA]=20=EA=B3=B5=ED=95=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_10775.java | 95 ++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_10775.java diff --git a/java/BOJ/Gold/II/G2_10775.java b/java/BOJ/Gold/II/G2_10775.java new file mode 100644 index 0000000..3ea4388 --- /dev/null +++ b/java/BOJ/Gold/II/G2_10775.java @@ -0,0 +1,95 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/10775 + * + * ! 제목: 공항 + * ! 시간 제한: 1초 + * ! 메모리 제한: 256MB + * + * ! 문제 + * 오늘은 신승원의 생일이다. + * 박승원은 생일을 맞아 신승원에게 인천국제공항을 선물로 줬다. + * 공항에는 G개의 게이트가 있으며 각각은 1에서 G까지의 번호를 가지고 있다. + * 공항에는 P개의 비행기가 순서대로 도착할 예정이며, 당신은 i번째 비행기를 1번부터 gi (1 ≤ gi ≤ G) 번째 게이트중 하나에 영구적으로 도킹하려 한다. 비행기가 어느 게이트에도 도킹할 수 없다면 공항이 폐쇄되고, 이후 어떤 비행기도 도착할 수 없다. + * 신승원은 가장 많은 비행기를 공항에 도킹시켜서 박승원을 행복하게 하고 싶어한다. 승원이는 비행기를 최대 몇 대 도킹시킬 수 있는가? + * + * ! 입력 & 파싱 + * 첫 번째 줄에는 게이트의 수 G (1 ≤ G ≤ 105)가 주어진다. + * 두 번째 줄에는 비행기의 수 P (1 ≤ P ≤ 105)가 주어진다. + * 이후 P개의 줄에 gi (1 ≤ gi ≤ G) 가 주어진다. + * + * 4 -> g + * 3 -> p + * 4 -> dock + * 1 -> dock + * 1 -> dock + * + * ! 출력 + * 승원이가 도킹시킬 수 있는 최대의 비행기 수를 출력한다. + * + * 2 + * + * ? 채점 결과 + * 시간: 364ms + * 메모리: 29036KB + */ +package Gold.II; + +import java.io.*; +import java.util.stream.IntStream; + +public class G2_10775 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + public static void main(String[] args) throws IOException { + // * 파싱 + int g = Integer.parseInt(br.readLine()); + int p = Integer.parseInt(br.readLine()); + + // * 분리 집합(UNION_FIND) + int[] parent = IntStream.range(0, g+1).toArray(); + + // * 도킹 완료된 비행기의 수 + int count = 0; + + // * 순서대로 들어오는 모든 비행기에 대해서 + for (int i = 0; i < p; i++) { + int dock = Integer.parseInt(br.readLine()); // * 현재 비행기의 번호 + union(parent, dock, parent[dock]); // * UNION_FIND => 도킹 가능한 게이트 번호를 찾음. + + dock = parent[dock]; // * 도킹 가능한 곳을 dock에 저장 + if (dock == 0) break; // * 도킹할 곳이 더이상 없으면 폐쇠하고 종료 + + parent[dock] -= 1; // * 도킹 완료시 해당 게이트의 분리집합 값을 -1 (Greedy) + count++; + } + + bw.write(String.valueOf(count)); + + bw.flush(); + br.close(); + bw.close(); + } + + // * UNION_FIND 함수 + public static boolean union(int[] parent, int a, int b) { + a = findParent(parent, a); + b = findParent(parent, b); + + if (a == b) return false; + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + return true; + } + + public static int findParent(int[] parent, int node) { + if (parent[node] != node) { + parent[node] = findParent(parent, parent[node]); + } + return parent[node]; + } +} From 55bfd3191d04eaa45a11b4b4dba93bc68f4efa49 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 25 Jul 2022 11:10:19 +0900 Subject: [PATCH 004/163] =?UTF-8?q?[BOJ-3584-JAVA]=20=EA=B0=80=EC=9E=A5=20?= =?UTF-8?q?=EA=B0=80=EA=B9=8C=EC=9A=B4=20=EA=B3=B5=ED=86=B5=20=EC=A1=B0?= =?UTF-8?q?=EC=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_3584.java | 123 ++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_3584.java diff --git a/java/BOJ/Gold/IV/G4_3584.java b/java/BOJ/Gold/IV/G4_3584.java new file mode 100644 index 0000000..6734c95 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_3584.java @@ -0,0 +1,123 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/3584 + * + * ! 제목: 가장 가까운 공통 조상 + * ! 시간 제한: 1초 + * ! 메모리 제한: 128MB + * + * ! 문제 + * 루트가 있는 트리(rooted tree)가 주어지고, 그 트리 상의 두 정점이 주어질 때 그들의 가장 가까운 공통 조상(Nearest Common Anscestor)은 다음과 같이 정의됩니다. + * 두 노드의 가장 가까운 공통 조상은, 두 노드를 모두 자손으로 가지면서 깊이가 가장 깊은(즉 두 노드에 가장 가까운) 노드를 말합니다. + * 예를 들어 15와 11를 모두 자손으로 갖는 노드는 4와 8이 있지만, 그 중 깊이가 가장 깊은(15와 11에 가장 가까운) 노드는 4 이므로 가장 가까운 공통 조상은 4가 됩니다. + * 루트가 있는 트리가 주어지고, 두 노드가 주어질 때 그 두 노드의 가장 가까운 공통 조상을 찾는 프로그램을 작성하세요 + * + * ! 입력 & 파싱 + * 첫 줄에 테스트 케이스의 개수 T가 주어집니다. + * 각 테스트 케이스마다, 첫째 줄에 트리를 구성하는 노드의 수 N이 주어집니다. (2 ≤ N ≤ 10,000) + * 그리고 그 다음 N-1개의 줄에 트리를 구성하는 간선 정보가 주어집니다. 한 간선 당 한 줄에 두 개의 숫자 A B 가 순서대로 주어지는데, 이는 A가 B의 부모라는 뜻입니다. (당연히 정점이 N개인 트리는 항상 N-1개의 간선으로 이루어집니다!) A와 B는 1 이상 N 이하의 정수로 이름 붙여집니다. + * 테스트 케이스의 마지막 줄에 가장 가까운 공통 조상을 구할 두 노드가 주어집니다. + * + * 2 -> t + * 16 -> n + * 1 14 -> a b + * 8 5 -> a b + * 10 16 -> a b + * 5 9 -> a b + * 4 6 -> a b + * 8 4 -> a b + * 4 10 -> a b + * 1 13 -> a b + * 6 15 -> a b + * 10 11 -> a b + * 6 7 -> a b + * 10 2 -> a b + * 16 3 -> a b + * 8 1 -> a b + * 16 12 -> a b + * 16 7 -> node1 node2 + * 5 -> n + * 2 3 -> a b + * 3 4 -> a b + * 3 1 -> a b + * 1 5 -> a b + * 3 5 -> node1 node2 + * + * ! 출력 + * 각 테스트 케이스 별로, 첫 줄에 입력에서 주어진 두 노드의 가장 가까운 공통 조상을 출력합니다. + * + * 4 + * 3 + * + * ? 채점 결과 + * 시간: 200ms + * 메모리: 22544KB + * 언어: JAVA8 + */ +package Gold.IV; + +import java.io.*; +import java.util.StringTokenizer; + +public class G4_3584 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 초기 설정 + static int n, arr[], node1, node2; + + // * 메인 함수 + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); // 테스트 케이스 갯수 + + // 각 테스트케이스만큼 반복 + for (int i = 0; i < t; i++) { + input(); // 입력 받기 + int result = findParent(node1, node2); // * 가장 가까운 공통조상 찾기 + bw.write(String.valueOf(result + "\n")); // 출력 + } + + // * 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // * 가장 가까운 공통조상 찾기 + public static int findParent(int a, int b) { + boolean[] visited = new boolean[n+1]; // * 방문 리스트 + + // * node1의 부모들을 모두 방문표시(루트노드까지) + while (a != 0) { + visited[a] = true; + a = arr[a]; + } + + // * node2의 부모를 거슬러 올라가다가 이미 방문한 위치가 있다면 해당 노드 리턴 + while (b != 0) { + if (visited[b]) { + return b; + } + b = arr[b]; + } + return -1; + } + + // * 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); // * 노드 개수 + arr = new int[n+1]; // * 부모 배열 + for (int i = 0; i < n-1; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + arr[b] = a; // ! b의 부모가 a임을 표시 + } + + // * 공통조상 찾아야 하는 두 노드 + st = new StringTokenizer(br.readLine()); + node1 = Integer.parseInt(st.nextToken()); + node2 = Integer.parseInt(st.nextToken()); + } +} From 565814cdfafb007e9d3f307c0374f1fb7d1bc549 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 26 Jul 2022 13:24:45 +0900 Subject: [PATCH 005/163] =?UTF-8?q?[BOJ-1208-JAVA]=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=EC=88=98=EC=97=B4=EC=9D=98=20=ED=95=A9=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_1208.java | 126 +++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 java/BOJ/Gold/I/G1_1208.java diff --git a/java/BOJ/Gold/I/G1_1208.java b/java/BOJ/Gold/I/G1_1208.java new file mode 100644 index 0000000..c56a8a2 --- /dev/null +++ b/java/BOJ/Gold/I/G1_1208.java @@ -0,0 +1,126 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/1208 + * + * ! 제목: 부분수열의 합 2 + * ! 시간 제한: 1초 + * ! 메모리 제한: 256MB + * + * ! 문제 + * N개의 정수로 이루어진 수열이 있을 때, 크기가 양수인 부분수열 중에서 그 수열의 원소를 다 더한 값이 S가 되는 경우의 수를 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 40, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다. + * + * 5 0 -> n s + * -7 -3 -2 5 8 -> arr + * + * ! 출력 + * 첫째 줄에 합이 S가 되는 부분수열의 개수를 출력한다. + * + * 1 + * + * ? 채점 결과 + * 시간: 848ms + * 메모리: 30848KB + * 언어: JAVA8 + */ +package Gold.I; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G1_1208 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, s, arr[]; + // 초기 설정 + static long count = 0; + + public static void main(String[] args) throws IOException { + input(); + int half = n / 2; + int[] a = new int[1 << (n-half)]; + int[] b = new int[1 << half]; + + // ! 2의 (n-half)제곱의 경우의 수만큼 부분수열이 생김 + for (int i = 0; i < (1 << n-half); i++) { + for (int j = 0; j < n-half; j++) { + if (((1 << j) & i) != 0) { + a[i] += arr[j]; + } + } + } + + // ! 2의 half 제곱의 경우의 수만ㄴ큼 부분수열이 생김 + for (int i = 0; i < (1 << half); i++) { + for (int j = 0; j < half; j++) { + if (((1 << j) & i) != 0) { + b[i] += arr[n-half+j]; + } + } + } + + // * 두 배열 모두 정렬 + Arrays.sort(a); + Arrays.sort(b); + + // * 투 포인터를 이용한 부분집합들 + int ap = 0; + int bp = b.length-1; + + // * 합이 s가 되는 구간들을 곱함 + // A가 1부터 3까지 3개가 같은값 + // B가 1부터 2까지 2개가 같은값 + // 이라면, + // count += 3 * 2 + while (ap < a.length && bp >= 0) { + int av = a[ap]; + int bv = b[bp]; + + if (av + bv > s) { + bp--; + } else if (av + bv < s) { + ap++; + } else { + long ac = 0; + long bc = 0; + + while (ap < a.length && av == a[ap]) { + ac++; + ap++; + } + + while (bp >= 0 && bv == b[bp]) { + bc++; + bp--; + } + + count += (ac * bc); + } + } + + if (s == 0) count--; // 크기가 양수인 부분집합이어야 하므로 s가 0일 경우에 카운트 1개를 빼줌 + bw.write(String.valueOf(count)); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + s = Integer.parseInt(st.nextToken()); + + arr = new int[n]; + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + } +} From d552f7af6eeb65887481c9f2319cccfdfa90e26b Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 27 Jul 2022 13:12:38 +0900 Subject: [PATCH 006/163] =?UTF-8?q?[BOJ-9527-JAVA]=201=EC=9D=98=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=EC=84=B8=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_9527.java | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_9527.java diff --git a/java/BOJ/Gold/II/G2_9527.java b/java/BOJ/Gold/II/G2_9527.java new file mode 100644 index 0000000..0dbd169 --- /dev/null +++ b/java/BOJ/Gold/II/G2_9527.java @@ -0,0 +1,85 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/9527 + * + * ! 제목: 1의 개수 세기 + * ! 시간 제한: 1초 + * ! 메모리 제한: 128MB + * + * ! 문제 + * 두 자연수 A, B가 주어졌을 때, A ≤ x ≤ B를 만족하는 모든 x에 대해 x를 이진수로 표현했을 때 1의 개수의 합을 구하는 프로그램을 작성하시오. + * 즉, f(x) = x를 이진수로 표현 했을 때 1의 개수라고 정의하고, 아래 식의 결과를 구하자. + * + * ! 입력 & 파싱 + * 첫 줄에 두 자연수 A, B가 주어진다. (1 ≤ A ≤ B ≤ 1016) + * + * 2 12 -> a b + * + * ! 출력 + * 1의 개수를 세어 출력한다. + * + * 21 + * + * ? 채점 결과 + * 시간: 76ms + * 메모리: 11636KB + * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.StringTokenizer; + +public class G2_9527 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static long a, b; + + // ! 초기 설정 : 1의 갯수 누적합 => arr[n]: 2진법 n의 자리수까지의 1의 개수의 총합 + static long[] arr = new long[55]; + + // 메인 + public static void main(String[] args) throws IOException { + input(); // 입력 받기 + arr[0] = 0L; // 초기값 설정 + + // ! 점화식을 이용한 누적합 구하기 + for (int i = 1; i <= 54; i++) { + arr[i] = (long) Math.pow(2, i-1) + 2 * arr[i-1]; + } + + // ! b 까지의 1의개수 누적합 - (a-1)까지의 1의개수 누적합 출력 + bw.write(String.valueOf(getOne(b) - getOne(a-1))); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // 누적합구하기 + public static long getOne(long num) { + long answer = 0L; + String bin_num = Long.toBinaryString(num); + int length = bin_num.length(); + for (int i = 0; i < length; i++) { + if (bin_num.charAt(i) == '1') { + int pow = length - i - 1; + answer += num - ((long) Math.pow(2, pow) - 1); + answer += arr[pow]; + num -= (long) Math.pow(2, pow); + } + } + return answer; + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + a = Long.parseLong(st.nextToken()); + b = Long.parseLong(st.nextToken()); + } +} \ No newline at end of file From 8b7d2adcf5de6ab16a26b71b61998d541c2950fa Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 28 Jul 2022 16:40:22 +0900 Subject: [PATCH 007/163] =?UTF-8?q?[BOJ-JAVA-1103]=20=EA=B2=8C=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_1103.java | 116 ++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_1103.java diff --git a/java/BOJ/Gold/II/G2_1103.java b/java/BOJ/Gold/II/G2_1103.java new file mode 100644 index 0000000..606d4f1 --- /dev/null +++ b/java/BOJ/Gold/II/G2_1103.java @@ -0,0 +1,116 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/1103 + * + * ! 제목: 게임 + * ! 시간 제한: 2초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 형택이는 1부터 9까지의 숫자와, 구멍이 있는 직사각형 보드에서 재밌는 게임을 한다. + * 일단 보드의 가장 왼쪽 위에 동전을 하나 올려놓는다. 그다음에 다음과 같이 동전을 움직인다. + * 동전이 있는 곳에 쓰여 있는 숫자 X를 본다. + * 위, 아래, 왼쪽, 오른쪽 방향 중에 한가지를 고른다. + * 동전을 위에서 고른 방향으로 X만큼 움직인다. 이때, 중간에 있는 구멍은 무시한다. + * 만약 동전이 구멍에 빠지거나, 보드의 바깥으로 나간다면 게임은 종료된다. 형택이는 이 재밌는 게임을 되도록이면 오래 하고 싶다. + * 보드의 상태가 주어졌을 때, 형택이가 최대 몇 번 동전을 움직일 수 있는지 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 줄에 보드의 세로 크기 N과 가로 크기 M이 주어진다. 이 값은 모두 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 보드의 상태가 주어진다. 쓰여 있는 숫자는 1부터 9까지의 자연수 또는 H이다. 가장 왼쪽 위칸은 H가 아니다. H는 구멍이다. + * + * 3 7 -> n m + * 3942178 -> board[0][0] ~ board[0][m-1] + * 1234567 + * 9123532 -> board[n-1][0] ~ board[n-1][m-1] + * + * ! 출력 + * 첫째 줄에 문제의 정답을 출력한다. 만약 형택이가 동전을 무한번 움직일 수 있다면 -1을 출력한다. + * + * 5 + * + * ? 채점 결과 + * 시간: 88ms + * 메모리: 12492KB + * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.StringTokenizer; + +public class G2_1103 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, m; + static char[][] board; + + // 초기 설정 + static int[] dx = {1, -1, 0, 0}; // 상하 + static int[] dy = {0, 0, 1, -1}; // 좌우 + + static boolean[][] visited; // 방문리스트 + static int[][] dp; // DP를 이용한 게임가능횟수 저장 배열 + + // * 메인 + public static void main(String[] args) throws IOException { + input(); // 입력 받기 + + // * 맨 왼쪽 위에서부터 시작 + visited[0][0] = true; + dfs(0, 0); + + // * (0, 0) 에서의 게임 가능 횟수가 10000보다 크면 싸이클이 발생하므로 -1을 출력, 그 외에는 dp[0][0]출력 + bw.write(String.valueOf(dp[0][0] >= 10000 ? -1 : dp[0][0])); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + public static int dfs(int x, int y) { + // * 이미 게임 횟수가 정해진 곳에 방문했을 때 + if (dp[x][y] > 0) return dp[x][y]; + + for (int i = 0; i < 4; i++) { + // * 해당 위치의 숫자만큼 상하좌우로 이동할 때의 nx, ny + int num = Integer.parseInt(String.valueOf(board[x][y])); + int nx = x + num * dx[i]; + int ny = y + num * dy[i]; + + // * 밤위를 벗어나거나 H(구멍)에 빠지게 될 경우 dp[x][y]의 값을 1과 비교해서 큰 값으로 설정 + if (nx < 0 || ny < 0 || nx >= n || ny >= m || board[nx][ny] == 'H') { + dp[x][y] = Math.max(dp[x][y], 1); + } else { + // * 이미 방문한 곳을 방문하여 무한번 게임 실행이 가능해질 때 + if (visited[nx][ny]) { + dp[x][y] = 10000; // * dp[x][y]를 10000으로 설정하고 종료 + break; + } else { + visited[nx][ny] = true; // * 방문표시 + dp[x][y] = Math.max(dp[x][y], dfs(nx, ny) + 1); // * 상하좌우로 이동한 곳의 게임 횟수+1 중 큰 값을 저장 + visited[nx][ny] = false; // * 방문 해제 + } + } + } + return dp[x][y]; // * 현재 자신 위치의 게임 가능 횟수를 리턴 + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + visited = new boolean[n][m]; + board = new char[n][m]; + dp = new int[n][m]; + + for (int i = 0; i < n; i++) { + board[i] = br.readLine().toCharArray(); + } + } +} From bf0e2e38c1de203ea30ff287dcf79a1246c6850a Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 29 Jul 2022 14:05:45 +0900 Subject: [PATCH 008/163] =?UTF-8?q?[BOJ-16197-JAVA]=20=EB=91=90=20?= =?UTF-8?q?=EB=8F=99=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_16197.java | 168 +++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_16197.java diff --git a/java/BOJ/Gold/IV/G4_16197.java b/java/BOJ/Gold/IV/G4_16197.java new file mode 100644 index 0000000..74a3f0b --- /dev/null +++ b/java/BOJ/Gold/IV/G4_16197.java @@ -0,0 +1,168 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/16197 + * + * ! 제목: 두 동전 + * ! 시간 제한: 2초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * N×M 크기의 보드와 4개의 버튼으로 이루어진 게임이 있다. 보드는 1×1크기의 정사각형 칸으로 나누어져 있고, 각각의 칸은 비어있거나, 벽이다. 두 개의 빈 칸에는 동전이 하나씩 놓여져 있고, 두 동전의 위치는 다르다. + * 버튼은 "왼쪽", "오른쪽", "위", "아래"와 같이 4가지가 있다. 버튼을 누르면 두 동전이 버튼에 쓰여 있는 방향으로 동시에 이동하게 된다. + * 동전이 이동하려는 칸이 벽이면, 동전은 이동하지 않는다. + * 동전이 이동하려는 방향에 칸이 없으면 동전은 보드 바깥으로 떨어진다. + * 그 외의 경우에는 이동하려는 방향으로 한 칸 이동한다.이동하려는 칸에 동전이 있는 경우에도 한 칸 이동한다. + * 두 동전 중 하나만 보드에서 떨어뜨리기 위해 버튼을 최소 몇 번 눌러야하는지 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 보드의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 20) + * 둘째 줄부터 N개의 줄에는 보드의 상태가 주어진다. + * + * o: 동전 + * .: 빈 칸 + * #: 벽 + * 동전의 개수는 항상 2개이다. + * + * 6 2 -> n m + * .# -> arr[0][0] ~ arr[0][m-1] + * .# + * .# + * o# + * o# + * ## -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ! 출력 + * 첫째 줄에 두 동전 중 하나만 보드에서 떨어뜨리기 위해 눌러야 하는 버튼의 최소 횟수를 출력한다. 만약, 두 동전을 떨어뜨릴 수 없거나, 버튼을 10번보다 많이 눌러야 한다면, -1을 출력한다. + * + * 4 + * + * ? 채점 결과 + * 시간: 80ms + * 메모리: 11868KB + * 언어: JAVA8 + */ +package Gold.IV; + +import java.io.*; +import java.util.*; + +public class G4_16197 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + private static int n, m; + private static char[][] arr; + + // 초기 설정 + static int answer = -1; // 정답 + static int[] dx = {1, -1, 0, 0}; // 상하 + static int[] dy = {0, 0, 1, -1}; // 좌우 + static int[][] coin = new int[2][2]; // 초기 동전의 위치 + + // * 메인 + public static void main(String[] args) throws IOException { + + // TODO: 총 4가지 단계 풀이 + input(); // * 입력 받기 + findCoin(); // * 초기 동전의 위치 찾기 + bfs(); // * BFS 수행 + bw.write(String.valueOf(answer)); // * 정답 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static void bfs() { + LinkedList queue = new LinkedList<>(); // * BFS용 queue + boolean[][][][] visited = new boolean[n][m][n][m]; // * 20 x 20 x 20 x 20 4차원 방문표시 배열(16만의 boolean 가능) + + visited[coin[0][0]][coin[0][1]][coin[1][0]][coin[1][1]] = true; + queue.add(new int[] {coin[0][0], coin[0][1], coin[1][0], coin[1][1], 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + int x1 = cur[0]; + int y1 = cur[1]; + int x2 = cur[2]; + int y2 = cur[3]; + int count = cur[4]; + + if (count >= 10) continue; // * 10번을 넘게 이동한 경우 중지 + if (x1 == x2 && y1 == y2) continue; // * 동전이 겹치게 되는 경우 중지 + + // * 상하좌우에 대하여 + for (int i = 0; i < 4; i++) { + // * 동전 1의 다음 위치 + int nx1 = x1 + dx[i]; + int ny1 = y1 + dy[i]; + + // * 동전 2의 다음 위치 + int nx2 = x2 + dx[i]; + int ny2 = y2 + dy[i]; + + if (!valueCheck(nx1, ny1) && !valueCheck(nx2, ny2)) { // ! 모두 밖으로 떨어지면 중지 + continue; + } else if ((valueCheck(nx1, ny1) && !valueCheck(nx2 ,ny2)) || (!valueCheck(nx1, ny1) && valueCheck(nx2, ny2))) { + // ! 둘 중 하나만 떨어지면 정답에 count+1 저장 후 전체 종료 + answer = count+1; + return; + } else { + // ! 두 동전 모두 안떨어지고 있으면 큐에 넣어 계속 진행 + if (arr[nx1][ny1] == '#') { // * 벽이 있다면 nx -> x, ny -> y 원래대로 복귀(이동하지 못함) + nx1 = x1; + ny1 = y1; + } + + if (arr[nx2][ny2] == '#') { // * 벽이 있다면 nx -> x, ny -> y 원래대로 복귀(이동하지 못함) + nx2 = x2; + ny2 = y2; + } + + // * 이미 방문하지 않은 위치에 대해서 + if (!visited[nx1][ny1][nx2][ny2]) { + visited[nx1][ny1][nx2][ny2] = true; // * 방문 표시 + queue.add(new int[] {nx1 ,ny1, nx2, ny2, count+1}); // * 큐에 삽입 + } + } + + } + } + } + + // * 보드의 크기 안에 좌표가 들어가있는지 검사하는 함수 + public static boolean valueCheck(int x, int y) { + return 0 <= x && x < n && 0 <= y && y < m; + } + + // * 초기 동전의 위치를 찾는 함수 + public static void findCoin() { + byte count = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (arr[i][j] == 'o') { + coin[count++] = new int[] {i, j}; + arr[i][j] = '.'; + } + + if (count >= 3) break; + } + } + } + + // * 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new char[n][m]; + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } +} From 7322db9ead77586fbc0706e5179d9efcb8f0a180 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 30 Jul 2022 16:07:06 +0900 Subject: [PATCH 009/163] =?UTF-8?q?[BOJ-2637-JAVA]=20=EC=9E=A5=EB=82=9C?= =?UTF-8?q?=EA=B0=90=20=EC=A1=B0=EB=A6=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_2637.java | 135 ++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_2637.java diff --git a/java/BOJ/Gold/II/G2_2637.java b/java/BOJ/Gold/II/G2_2637.java new file mode 100644 index 0000000..bdffc3a --- /dev/null +++ b/java/BOJ/Gold/II/G2_2637.java @@ -0,0 +1,135 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/2637 + * + * ! 제목: 장난감 조립 + * ! 시간 제한: 1초 + * ! 메모리 제한: 128MB + * + * ! 문제 + * 우리는 어떤 장난감을 여러 가지 부품으로 조립하여 만들려고 한다. 이 장난감을 만드는데는 기본 부품과 그 기본 부품으로 조립하여 만든 중간 부품이 사용된다. 기본 부품은 다른 부품을 사용하여 조립될 수 없는 부품이다. 중간 부품은 또 다른 중간 부품이나 기본 부품을 이용하여 만들어지는 부품이다. + * 예를 들어보자. 기본 부품으로서 1, 2, 3, 4가 있다. 중간 부품 5는 2개의 기본 부품 1과 2개의 기본 부품 2로 만들어진다. 그리고 중간 부품 6은 2개의 중간 부품 5, 3개의 기본 부품 3과 4개의 기본 부품 4로 만들어진다. 마지막으로 장난감 완제품 7은 2개의 중간 부품 5, 3개의 중간 부품 6과 5개의 기본 부품 4로 만들어진다. 이런 경우에 장난감 완제품 7을 만드는데 필요한 기본 부품의 개수는 1번 16개, 2번 16개, 3번 9개, 4번 17개이다. + * 이와 같이 어떤 장난감 완제품과 그에 필요한 부품들 사이의 관계가 주어져 있을 때 하나의 장난감 완제품을 조립하기 위하여 필요한 기본 부품의 종류별 개수를 계산하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에는 자연수 N(3 ≤ N ≤ 100)이 주어지는데, 1부터 N-1까지는 기본 부품이나 중간 부품의 번호를 나타내고, N은 완제품의 번호를 나타낸다. 그리고 그 다음 줄에는 자연수 M(3 ≤ M ≤ 100)이 주어지고, 그 다음 M개의 줄에는 어떤 부품을 완성하는데 필요한 부품들 간의 관계가 3개의 자연수 X, Y, K로 주어진다. 이 뜻은 "중간 부품이나 완제품 X를 만드는데 중간 부품 혹은 기본 부품 Y가 K개 필요하다"는 뜻이다. 두 중간 부품이 서로를 필요로 하는 경우가 없다. + * + * 7 -> n + * 8 -> m + * 5 1 2 -> x y z + * 5 2 2 -> x y z + * 7 5 2 -> x y z + * 6 5 2 -> x y z + * 6 3 3 -> x y z + * 6 4 4 -> x y z + * 7 6 3 -> x y z + * 7 4 5 -> x y z + * + * ! 출력 + * 하나의 완제품을 조립하는데 필요한 기본 부품의 수를 한 줄에 하나씩 출력하되(중간 부품은 출력하지 않음), 반드시 기본 부품의 번호가 작은 것부터 큰 순서가 되도록 한다. 각 줄에는 기본 부품의 번호와 소요 개수를 출력한다. + * 정답은 2,147,483,647 이하이다. + * + * 1 16 + * 2 16 + * 3 9 + * 4 17 + * + * ? 채점 결과 + * 시간: 80ms + * 메모리: 11800KB + * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.StringTokenizer; + +public class G2_2637 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, m; + + // 초기 설정 + static int[] basicParts, degree, result; + static ArrayList[] list; + + // 부품 번호와 갯수를 의미하는 노드 클래스 + public static class Node { + int num; + int count; + + public Node(int num, int count) { + this.num = num; + this.count = count; + } + } + + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + topologicalSort(); // * 위상 정렬 + + // * 기본부품인 경우에만 필요한 부품수 출력 + for (int i = 1; i <= n; i++) { + if (basicParts[i] == 0) { + bw.write(String.valueOf(i) + " " + String.valueOf(result[i]) + "\n"); + } + } + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 위상 정렬 + public static void topologicalSort() { + LinkedList queue = new LinkedList<>(); + queue.add(new Node(n, 1)); // 완제품 번호(n)와 갯수(1)을 삽입 + result[n] = 1; // 필요한 완제품의 갯수 1로 설정 + + while (!queue.isEmpty()) { + Node cur = queue.poll(); + + // * 현재 부품을 만들기 위해 필요한 부품들에 대하여 + for (Node next: list[cur.num]) { + result[next.num] += result[cur.num] * next.count; // * 현재 부품의 필요한 개수 x 현재 부품 1개를 만들기 위해 필요한 부속 부품의 개수 + // * 더이상 해당 부속 부품을 필요로하는 상위 부품이 없을 때 + if (--degree[next.num] == 0) { + queue.add(new Node(next.num, result[next.num])); // * 큐에 삽입 + } + } + } + } + + // * 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + m = Integer.parseInt(br.readLine()); + + list = new ArrayList[n+1]; + for (int i = 1; i <= n; i++) { + list[i] = new ArrayList<>(); + } + + basicParts = new int[n+1]; + degree = new int[n+1]; + result = new int[n+1]; + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int x = Integer.parseInt(st.nextToken()); + int y = Integer.parseInt(st.nextToken()); + int z = Integer.parseInt(st.nextToken()); + + list[x].add(new Node(y, z)); + basicParts[x]++; + degree[y]++; + + } + } +} From c404976034623f8b0bc4e422510ce4928ba6e5bd Mon Sep 17 00:00:00 2001 From: dongjji Date: Sun, 31 Jul 2022 15:49:13 +0900 Subject: [PATCH 010/163] =?UTF-8?q?[BOJ-1039-JAVA]=20=EA=B5=90=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_1039.java | 110 +++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_1039.java diff --git a/java/BOJ/Gold/III/G3_1039.java b/java/BOJ/Gold/III/G3_1039.java new file mode 100644 index 0000000..3e55057 --- /dev/null +++ b/java/BOJ/Gold/III/G3_1039.java @@ -0,0 +1,110 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/1039 + * + * ! 제목: 교환 + * ! 시간 제한: 2초 + * ! 메모리 제한: 128MB + * + * ! 문제 + * 0으로 시작하지 않는 정수 N이 주어진다. 이때, M을 정수 N의 자릿수라고 했을 때, 다음과 같은 연산을 K번 수행한다. + * 1 ≤ i < j ≤ M인 i와 j를 고른다. 그 다음, i번 위치의 숫자와 j번 위치의 숫자를 바꾼다. 이때, 바꾼 수가 0으로 시작하면 안 된다. + * 위의 연산을 K번 했을 때, 나올 수 있는 수의 최댓값을 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 정수 N과 K가 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, K는 10보다 작거나 같은 자연수이다. + * + * 16375 1 -> num, k + * + * ! 출력 + * 첫째 줄에 문제에 주어진 연산을 K번 했을 때, 만들 수 있는 가장 큰 수를 출력한다. 만약 연산을 K번 할 수 없으면 -1을 출력한다. + * + * 76315 + * + * ? 채점 결과 + * 시간: 204ms + * 메모리: 59540KB + * 언어: JAVA8 + */ +package Gold.III; + +import java.io.*; +import java.util.LinkedList; + +public class G3_1039 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // 파싱 + static int num, k; + + // 초기 설정 + static int max = 0; + static int[][] visited; + + // * 메인 함수 + public static void main(String[] args) throws IOException { + String[] str = br.readLine().split(" "); + num = Integer.parseInt(str[0]); + k = Integer.parseInt(str[1]); + visited = new int[k+1][1000001]; + + bfs(num); // ! BFS + bw.write(String.valueOf(max == 0 ? -1 : max)); // * 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static void bfs(int start) { + LinkedList queue = new LinkedList<>(); + queue.add(new int[] {start, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + int num = cur[0]; // * 현재 숫자 + int count = cur[1]; // * 현재 숫자의 자릿수 교환 횟수 + + if (count == k) continue; // * K번만큼 바꿨다면 패스 + + String s = Integer.toString(num); // * 현재 숫자를 문자열로 변환 + for (int i = 0; i < s.length()-1; i++) { + for (int j = i+1; j < s.length(); j++) { + if (i == 0 && s.charAt(j) == '0') continue; // * 맨 앞자리와 0을 바꾸는 경우가 없이 + + String newStr = swap(s, i, j); // * 문자열의 i와 j를 스왑한 문자열을 반환 + int newNum = Integer.parseInt(newStr);// * 위 문자열을 다시 숫자로 변환 + + // * count+1 횟수로 newNum의 숫자로 도달한 경우가 없을 때만 + if (visited[count+1][newNum] == 0) { + visited[count+1][newNum] = 1; // * 방문표시 후 + queue.add(new int[] {newNum, count+1}); // * 큐에 삽입 + } + } + } + } + + // * visited[k]의 숫자들 중 (총 K번 교환이 완료된 숫자들 중) + for (int i = 0; i < visited[k].length; i++) { + if (visited[k][i] != 0) { // * 방문표시가 되어있는 인덱스의 숫자들 중 가장 큰 값을 max에 저장 + if (max < i) { + max = i; + } + } + } + } + + // * 문자열과 i, j번째 인덱스의 문자를 서로 스왑하는 함수 + public static String swap(String s, int i, int j) { + char[] str = s.toCharArray(); + char temp = str[i]; + str[i] = str[j]; + str[j] = temp; + return String.valueOf(str); + } + + +} From 92d454253df7d25e7a082286355e70a5bb6583a0 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 1 Aug 2022 17:43:17 +0900 Subject: [PATCH 011/163] =?UTF-8?q?[BOJ-1507-JAVA]=20=EA=B6=81=EA=B8=88?= =?UTF-8?q?=ED=95=9C=20=EB=AF=BC=ED=98=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_1507.java | 106 ++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_1507.java diff --git a/java/BOJ/Gold/II/G2_1507.java b/java/BOJ/Gold/II/G2_1507.java new file mode 100644 index 0000000..eaf5f23 --- /dev/null +++ b/java/BOJ/Gold/II/G2_1507.java @@ -0,0 +1,106 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/1507 + * + * ! 제목: 궁금한 민호 + * ! 시간 제한: 2초 + * ! 메모리 제한: 128MB + * + * ! 문제 + * 강호는 N개의 도시로 이루어진 나라에 살고 있다. 각 도시는 M개의 도로로 연결되어 있으며, 각 도로를 지날 때 필요한 시간이 존재한다. 도로는 잘 연결되어 있기 때문에, 도시 A에서 B로 이동할 수 없는 경우는 존재하지 않는다. + * 도시 A에서 도시 B로 바로 갈 수 있는 도로가 있거나, 다른 도시를 거쳐서 갈 수 있을 때, 도시 A에서 B를 갈 수 있다고 한다. + * 강호는 모든 쌍의 도시에 대해서 최소 이동 시간을 구해놓았다. 민호는 이 표를 보고 원래 도로가 몇 개 있는지를 구해보려고 한다. + * 예를 들어, 예제의 경우에 모든 도시 사이에 강호가 구한 값을 가지는 도로가 존재한다고 해도 된다. 하지만, 이 도로의 개수는 최솟값이 아니다. 예를 들어, 도시 1-2, 2-3, 1-4, 3-4, 4-5, 3-5를 연결하는 도로만 있다고 가정해도, 강호가 구한 모든 쌍의 최솟값을 구할 수 있다. 이 경우 도로의 개수는 6개이고, 모든 도로의 시간의 합은 55이다. + * 모든 쌍의 도시 사이의 최소 이동 시간이 주어졌을 때, 이 나라에 존재할 수 있는 도로의 개수의 최솟값일 때, 모든 도로의 시간의 합을 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 도시의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 각각의 도시 사이에 이동하는데 필요한 시간이 주어진다. A에서 B로 가는 시간과 B에서 A로 가는 시간은 같다. 또, A와 B가 같은 경우에는 0이 주어지고, 그 외의 경우에 필요한 시간은 2500보다 작거나 같은 자연수이다. + * + * 5 -> n + * 0 6 15 2 6 -> arr[0][0] ~ arr[0][n-1] + * 6 0 9 8 12 + * 15 9 0 16 18 + * 2 8 16 0 4 + * 6 12 18 4 0 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ! 출력 + * 첫째 줄에 도로 개수가 최소일 때, 모든 도로의 시간의 합을 출력한다. 불가능한 경우에는 -1을 출력한다. + * + * 55 + * + * ? 채점 결과 + * 시간: 84ms + * 메모리: 11688KB + * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.StringTokenizer; + +public class G2_1507 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, arr[][]; + + // 초기 설정 + static int total = 0; // 도로의 개수가 최솟값일 때, 모든 도로의 시간의 합 + static boolean[][] minRoad; // 도로의 개수가 최솟값이 되기 위해 선택하지 말아야 할 도로(true값이면 선택하지 않음) + static boolean result = true; // 불가능한 경우가 있는지 판단 + + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + floyd(); // * 플로이드 와샬 + + // * minRoad의 값이 true인 값을 제외하고 모든 도로의 길이를 더한다(중복 없이) + for (int i = 0; i < n-1; i++) { + for (int j = i+1; j < n; j++) { + if (!minRoad[i][j]) total += arr[i][j]; + } + } + + bw.write(String.valueOf(result ? total : -1)); // * 출력 + + br.close(); + bw.flush(); + bw.close(); + } + + // ! 플로이드 와샬 + public static void floyd() { + for (int k = 0; k < n; k++) { + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j || j == k || k == i) continue; + + // * 플로이드 와샬이 성립하지 않는 경우 종료 + if (arr[i][j] > arr[i][k] + arr[k][j]) { + result = false; + return; + } else if (arr[i][j] == arr[i][k] + arr[k][j]) { + // * i -> j로 가는 최소거리와 i -> k -> j로 가는 최소거리가 같다면 + // * i -> j로 가는 경로를 포함시킬 필요 없음(i -> k, k -> j만 선택해도 됨) + minRoad[i][j] = true; + } + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new int[n][n]; + minRoad = new boolean[n][n]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 1192b42ef22e315796c9e25d4cfda256e47ee01c Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 2 Aug 2022 15:34:51 +0900 Subject: [PATCH 012/163] =?UTF-8?q?[BOJ-17141-JAVA]=20=EC=97=B0=EA=B5=AC?= =?UTF-8?q?=EC=86=8C2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_17141.java | 195 +++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_17141.java diff --git a/java/BOJ/Gold/IV/G4_17141.java b/java/BOJ/Gold/IV/G4_17141.java new file mode 100644 index 0000000..c0fc095 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_17141.java @@ -0,0 +1,195 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/17141 + * + * ! 제목: 연구소2 + * ! 시간 제한: 1초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 승원이는 연구소의 특정 위치에 바이러스 M개를 놓을 것이고, 승원이의 신호와 동시에 바이러스는 퍼지게 된다. + * 연구소는 크기가 N×N인 정사각형으로 나타낼 수 있으며, 정사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다. + * 일부 빈 칸은 바이러스를 놓을 수 있는 칸이다. 바이러스는 상하좌우로 인접한 모든 빈 칸으로 동시에 복제되며, 1초가 걸린다. + * 예를 들어, 아래와 같이 연구소가 생긴 경우를 살펴보자. 0은 빈 칸, 1은 벽, 2는 바이러스를 놓을 수 있는 칸이다. + * + * 2 0 0 0 1 1 0 + * 0 0 1 0 1 2 0 + * 0 1 1 0 1 0 0 + * 0 1 0 0 0 0 0 + * 0 0 0 2 0 1 1 + * 0 1 0 0 0 0 0 + * 2 1 0 0 0 0 2 + * + * M = 3이고, 바이러스를 아래와 같이 놓은 경우 6초면 모든 칸에 바이러스를 퍼뜨릴 수 있다. 벽은 -, 바이러스를 놓은 위치는 0, 빈 칸은 바이러스가 퍼지는 시간으로 표시했다. + * + * 6 6 5 4 - - 2 + * 5 6 - 3 - 0 1 + * 4 - - 2 - 1 2 + * 3 - 2 1 2 2 3 + * 2 2 1 0 1 - - + * 1 - 2 1 2 3 4 + * 0 - 3 2 3 4 5 + * + * 시간이 최소가 되는 방법은 아래와 같고, 5초만에 모든 칸에 바이러스를 퍼뜨릴 수 있다. + * + * 0 1 2 3 - - 2 + * 1 2 - 3 - 0 1 + * 2 - - 2 - 1 2 + * 3 - 2 1 2 2 3 + * 3 2 1 0 1 - - + * 4 - 2 1 2 3 4 + * 5 + * - 3 2 3 4 5 + * 연구소의 상태가 주어졌을 때, 모든 빈 칸에 바이러스를 퍼뜨리는 최소 시간을 구해보자. + * + * ! 입력 & 파싱 + * 첫째 줄에 연구소의 크기 N(5 ≤ N ≤ 50), 놓을 수 있는 바이러스의 개수 M(1 ≤ M ≤ 10)이 주어진다. + * 둘째 줄부터 N개의 줄에 연구소의 상태가 주어진다. 0은 빈 칸, 1은 벽, 2는 바이러스를 놓을 수 있는 칸이다. 2의 개수는 M보다 크거나 같고, 10보다 작거나 같은 자연수이다. + * + * 7 3 -> n m + * 2 0 0 0 1 1 0 -> arr[0][0] ~ arr[0][n-1] + * 0 0 1 0 1 2 0 + * 0 1 1 0 1 0 0 + * 0 1 0 0 0 0 0 + * 0 0 0 2 0 1 1 + * 0 1 0 0 0 0 0 + * 2 1 0 0 0 0 2 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ! 출력 + * 연구소의 모든 빈 칸에 바이러스가 있게 되는 최소 시간을 출력한다. 바이러스를 어떻게 놓아도 모든 빈 칸에 바이러스를 퍼뜨릴 수 없는 경우에는 -1을 출력한다. + * + * 5 + * + * ? 채점 결과 + * 시간: 252ms + * 메모리: 42312KB + * 언어: JAVA8 + */ +package Gold.IV; + +import java.io.*; +import java.util.*; + +public class G4_17141 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, m; + static int[][] arr; + + // 초기 설정 + static int min = 10000; + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + static ArrayList list = new ArrayList<>(); + + // * 메인 + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + + // * 바이러스를 놓을 수 있는 모든 방법의 수 중에서 m개의 바이러스를 놓은 경우에만 BFS 실행 + for (int i = 0; i < (1 << list.size()); i++) { + List virusList = findVirus(i); // * 바이러스를 놓을 수 있는 경우 + + if (virusList.size() == m) { // * m개의 바이러스를 놓은 경우 + bfs(virusList); // * 해당 바이러스 리스트를 가지고 BFS 수행 + } + } + + // * 출력 + bw.write(String.valueOf(min == 10000 ? -1: min)); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static void bfs(List virusList) { + LinkedList queue = new LinkedList<>(); + int[][] visited = new int[n][n]; + int maxTime = 0; + + // * 방문리스트 -1로 초기화 + for (int[] v: visited) { + Arrays.fill(v, -1); + } + + // * m개의 바이러스 위치에 대하여 방문표시 후 큐에 삽입 + for (int[] virus: virusList) { + queue.add(virus); + visited[virus[0]][virus[1]] = 0; + } + + // * BFS 수행 + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (0 <= nx && nx < n && 0 <= ny && ny < n && visited[nx][ny] == -1 && arr[nx][ny] != 1) { + visited[nx][ny] = visited[cur[0]][cur[1]] + 1; + queue.add(new int[] {nx, ny}); + + if (maxTime < visited[nx][ny]) { + maxTime = visited[nx][ny]; + } + } + } + } + + boolean virused = check(visited); // * 벽을 제외한 모든 곳이 바이러스에 감염되었는지 확인 + + // * 벽을 제외한 모든 곳이 바이러스에 감염되었을 때, 기존에 모두 감염된 최소 시간과 비교하여 최솟값 업데이트 + if (virused && maxTime < min) { + min = maxTime; + } + } + + // ! 벽을 제외한 모든 곳이 바이러스에 감염되었는지 확인하는 함수 + public static boolean check(int[][] visited) { + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (arr[i][j] != 1 && visited[i][j] == -1) { + return false; + } + } + } + + return true; + } + + // ! 바이러스를 놓을 수 있는 모든 경우를 리스트에 담아 리턴 + public static List findVirus(int i) { + String s = Integer.toBinaryString(i); + List virusList = new ArrayList<>(); + + for (int k = 0; k < s.length(); k++) { + if (s.charAt(s.length() - k - 1) == '1') { + virusList.add(list.get(k)); + } + } + + return virusList; + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + arr = new int[n][n]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + if (arr[i][j] == 2) list.add(new int[] {i, j}); + } + } + } +} From 7fcfe69ec4a3f42c289077dd73fcad8319ad1976 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 3 Aug 2022 12:59:43 +0900 Subject: [PATCH 013/163] =?UTF-8?q?[BOJ-12015-JAVA]=20=EA=B0=80=EC=9E=A5?= =?UTF-8?q?=20=EA=B8=B4=20=EC=A6=9D=EA=B0=80=ED=95=98=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=97=B4=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_12015.java | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_12015.java diff --git a/java/BOJ/Gold/II/G2_12015.java b/java/BOJ/Gold/II/G2_12015.java new file mode 100644 index 0000000..c793ad8 --- /dev/null +++ b/java/BOJ/Gold/II/G2_12015.java @@ -0,0 +1,97 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/12015 + * + * ! 제목: 가장 긴 증가하는 부분 수열 2 + * ! 시간 제한: 1초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. + * 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다. + * + * ! 입력 & 파싱 + * 첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. + * 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000) + * + * 6 -> n + * 10 20 10 30 20 50 -> arr + * + * ! 출력 + * 첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다. + * + * 4 + * + * ? 채점 결과 + * 시간: 508ms + * 메모리: 125412KB + * 언어: JAVA8 +*/ +package Gold.II; + +import java.io.*; +import java.util.StringTokenizer; + +public class G2_12015 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, arr[]; + + // 초기 설정 + static int length; + static int[] answer; + + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + search(); // * 이분 탐색을 이용한 LIS + + bw.write(String.valueOf(length)); // * LIS 길이 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 이분탐색을 이용한 LIS + public static void search() { + answer = new int[n]; + + answer[0] = arr[0]; + length = 1; + + for (int i = 1; i < n; i++) { + if (answer[length-1] < arr[i]) { + answer[length++] = arr[i]; + } else { + int left = 0; + int right = length-1; + + while (left < right) { + int mid = (left + right) / 2; + if (answer[mid] < arr[i]) { + left = mid + 1; + } else { + right = mid; + } + } + + answer[left] = arr[i]; + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + 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()); + } + } +} From 94e2193d29a5841b7cb821d214cde3a9fd4138a2 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 3 Aug 2022 13:02:56 +0900 Subject: [PATCH 014/163] =?UTF-8?q?[BOJ-14003-JAVA]=20=EA=B0=80=EC=9E=A5?= =?UTF-8?q?=20=EA=B8=B4=20=EC=A6=9D=EA=B0=80=ED=95=98=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=97=B4=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Platinum/V/P5_14003.java | 126 ++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 java/BOJ/Platinum/V/P5_14003.java diff --git a/java/BOJ/Platinum/V/P5_14003.java b/java/BOJ/Platinum/V/P5_14003.java new file mode 100644 index 0000000..ba00b87 --- /dev/null +++ b/java/BOJ/Platinum/V/P5_14003.java @@ -0,0 +1,126 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/14003 + * + * ! 제목: 가장 긴 증가하는 부분 수열 5 + * ! 시간 제한: 3초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. + * 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다. + * + * ! 입력 & 파싱 + * 첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. + * 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (-1,000,000,000 ≤ Ai ≤ 1,000,000,000) + * + * 6 -> n + * 10 20 10 30 20 50 -> arr + * + * ! 출력 + * 첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다. + * 둘째 줄에는 정답이 될 수 있는 가장 긴 증가하는 부분 수열을 출력한다. + * + * 4 + * 10 20 30 50 + * + * ? 채점 결과 + * 시간: 1016ms + * 메모리: 326344KB + * 언어: JAVA8 + */ +package Platinum.V; + +import java.io.*; +import java.util.Stack; +import java.util.StringTokenizer; + +public class P5_14003 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, arr[]; + + // 초기 설정 + static int length; + static int[] series, dp; + + // * 메인 + public static void main(String[] args) throws IOException { + input(); // * 입력받기 + LIS(); // * 이분탐색을 이용한 LIS + + // 첫째 줄에 LIS 길이 저장 + StringBuffer sb = new StringBuffer(); + sb.append(length + "\n"); + + // 수열의 끝부터 시작해서 + // ? 가장 긴 증가하는 부분수열의 인덱스가 가장 큰 값부터 차례대로 찾음 + // 길이가 5였다면 + // 끝에서부터 인덱스가 4 -> 3 -> 2 -> 1 -> 0을 찾아서 스택에 넣음 + Stack stack = new Stack<>(); + for (int i = n-1; i >= 0; i--) { + if (dp[i] == length-1) { + length--; + stack.push(arr[i]); + } + } + + // * 스택의 맨 위부터 두번째 출력에 담음(가장 긴 증가하는 부분 수열 중 작은 값부터) + while (!stack.isEmpty()) { + sb.append(stack.pop() + " "); + } + + // * 출력 + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // ! 이분 탐색을 이용한 LIS와 각 수열의 수가 속하는 LIS의 인덱스를 dp배열에 저장하는 함수 + public static void LIS() { + series = new int[n]; + dp = new int[n]; + + series[0] = arr[0]; + dp[0] = 0; + length = 1; + + for (int i = 1; i < n; i++) { + if (series[length-1] < arr[i]) { + series[length++] = arr[i]; + dp[i] = length-1; + } else { + int left = 0; + int right = length-1; + + while (left < right) { + int mid = (left + right) / 2; + if (series[mid] < arr[i]) { + left = mid + 1; + } else { + right = mid; + } + } + + series[left] = arr[i]; + dp[i] = left; + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + 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()); + } + } +} From 2a6ba0c5af91b3d7504576ff3107476a7b58ec99 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 4 Aug 2022 13:05:00 +0900 Subject: [PATCH 015/163] =?UTF-8?q?[BOJ-14500-JAVA]=20=ED=85=8C=ED=8A=B8?= =?UTF-8?q?=EB=A1=9C=EB=AF=B8=EB=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_14500.java | 146 +++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_14500.java diff --git a/java/BOJ/Gold/IV/G4_14500.java b/java/BOJ/Gold/IV/G4_14500.java new file mode 100644 index 0000000..946f2ab --- /dev/null +++ b/java/BOJ/Gold/IV/G4_14500.java @@ -0,0 +1,146 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/14500 + * + * ! 제목: 테트로미노 + * ! 시간 제한: 2초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. + * 정사각형은 서로 겹치면 안 된다. + * 도형은 모두 연결되어 있어야 한다. + * 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다. + * 정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다. + * 아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다. + * 테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오. + * 테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다. + * + * ! 입력 & 파싱 + * 첫째 줄에 종이의 세로 크기 N과 가로 크기 M이 주어진다. (4 ≤ N, M ≤ 500) + * 둘째 줄부터 N개의 줄에 종이에 쓰여 있는 수가 주어진다. i번째 줄의 j번째 수는 위에서부터 i번째 칸, 왼쪽에서부터 j번째 칸에 쓰여 있는 수이다. 입력으로 주어지는 수는 1,000을 넘지 않는 자연수이다. + * + * 5 5 -> n m + * 1 2 3 4 5 -> arr[0][0] ~ arr[0][m-1] + * 5 4 3 2 1 + * 2 3 4 5 6 + * 6 5 4 3 2 + * 1 2 1 2 1 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ! 출력 + * 첫째 줄에 테트로미노가 놓인 칸에 쓰인 수들의 합의 최댓값을 출력한다. + * + * 19 + * + * ? 채점 결과 + * 시간: 616ms + * 메모리: 31684KB + * 언어: JAVA8 + */ +package Gold.IV; + +import java.io.*; +import java.util.StringTokenizer; + +public class G4_14500 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // 파싱 + static int n, m; + static int[][] arr; + + // 초기 설정 + static int max = 0; + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + static boolean[][] visited; + + // * 메인 + public static void main(String[] args) throws IOException { + input(); // * 입력받기 + + // * 모든 위치에서 DFS수행 + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + // * DFS 수행 후 방문 표시 해제 + visited[i][j] = true; + dfs(i, j, 1, arr[i][j]); + visited[i][j] = false; + + // * DFS로 구할 수 없는 경우 계산 + // * 'ㅗ' 'ㅓ' 'ㅏ' 'ㅜ' 경우 중 최대값만 생각하여 계산 + int count = 1; + int min = 1000; + int sum = arr[i][j]; + + for (int k = 0; k < 4; k++) { + int ni = i + dx[k]; + int nj = j + dy[k]; + + if (0 <= ni && ni < n && 0 <= nj && nj < m) { + count++; + sum += arr[ni][nj]; + min = Math.min(arr[ni][nj], min); + } + } + + // * 위 네가지 경우가 모두 가능한 경우: 상하좌우값 중 최솟값을 빼서 4개블럭의 합의 최댓값만 취급하여 max값과 비교하여 업데이트 + if (count == 5) { + max = Math.max(sum - min, max); + } else if (count == 4) { + // * 위 네가지 경우 중 한가지만 가능한 경우: max값과 비교하여 바로 업데이트 + max = Math.max(sum, max); + } + } + } + + bw.write(String.valueOf(max)); // * 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! DFS + public static void dfs(int x, int y, int count, int sum) { + // * 4번의 이동이 끝났다면 종료 + if (count == 4) { + max = Math.max(sum, max); + return; + } + + // * 상하좌우에 대하여 DFS 재귀 수행 + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + // * 범위체크 + 방문체크 + if (0 <= nx && nx < n && 0 <= ny && ny < m && !visited[nx][ny]) { + // * DFS가 완료되면 방문표시 해제 + visited[nx][ny] = true; + dfs(nx, ny, count+1, sum + arr[nx][ny]); + visited[nx][ny] = false; + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n][m]; + visited = new boolean[n][m]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 23942a1dd44f411f3f8a1a22d8cdbe933ead488b Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 4 Aug 2022 13:08:13 +0900 Subject: [PATCH 016/163] =?UTF-8?q?=EB=9E=AD=ED=82=B9=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BOJ_RANK.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BOJ_RANK.md b/BOJ_RANK.md index 3b8dfb7..ddd79d0 100644 --- a/BOJ_RANK.md +++ b/BOJ_RANK.md @@ -12,12 +12,12 @@ #### 🏆 플래티넘 +[![백준랭킹](http://mazassumnida.wtf/api/v2/generate_badge?boj=y2kdj9723)](https://solved.ac/y2kdj9723) +
#### 🏆 골드 -[![백준랭킹](http://mazassumnida.wtf/api/v2/generate_badge?boj=y2kdj9723)](https://solved.ac/y2kdj9723) -
#### 🏆 실버 From f1c722e86d8b7ceb762c9e778809d2b676e75baa Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 5 Aug 2022 12:57:01 +0900 Subject: [PATCH 017/163] =?UTF-8?q?[BOJ-2887-JAVA]=20=ED=96=89=EC=84=B1=20?= =?UTF-8?q?=ED=84=B0=EB=84=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Platinum/V/P5_2887.java | 143 +++++++++++++++++++++++++++++++ java/BOJ/failed/P5_2887.java | 77 ----------------- 2 files changed, 143 insertions(+), 77 deletions(-) create mode 100644 java/BOJ/Platinum/V/P5_2887.java delete mode 100644 java/BOJ/failed/P5_2887.java diff --git a/java/BOJ/Platinum/V/P5_2887.java b/java/BOJ/Platinum/V/P5_2887.java new file mode 100644 index 0000000..61baf6a --- /dev/null +++ b/java/BOJ/Platinum/V/P5_2887.java @@ -0,0 +1,143 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/2887 + * + * ! 제목: 행성 터널 + * ! 시간 제한: 1초 + * ! 메모리 제한: 128MB + * + * ! 문제 + * 때는 2040년, 이민혁은 우주에 자신만의 왕국을 만들었다. 왕국은 N개의 행성으로 이루어져 있다. 민혁이는 이 행성을 효율적으로 지배하기 위해서 행성을 연결하는 터널을 만들려고 한다. + * 행성은 3차원 좌표위의 한 점으로 생각하면 된다. 두 행성 A(xA, yA, zA)와 B(xB, yB, zB)를 터널로 연결할 때 드는 비용은 min(|xA-xB|, |yA-yB|, |zA-zB|)이다. + * 민혁이는 터널을 총 N-1개 건설해서 모든 행성이 서로 연결되게 하려고 한다. 이때, 모든 행성을 터널로 연결하는데 필요한 최소 비용을 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 행성의 개수 N이 주어진다. (1 ≤ N ≤ 100,000) 다음 N개 줄에는 각 행성의 x, y, z좌표가 주어진다. 좌표는 -109보다 크거나 같고, 109보다 작거나 같은 정수이다. 한 위치에 행성이 두 개 이상 있는 경우는 없다. + * + * 5 -> n + * 11 -15 -15 -> x y z + * 14 -5 -15 -> x y z + * -1 -1 -5 -> x y z + * 10 -4 -1 -> x y z + * 19 -4 19 -> x y z + * + * ! 출력 + * 첫째 줄에 모든 행성을 터널로 연결하는데 필요한 최소 비용을 출력한다. + * + * 4 + * + * ? 채점 결과 + * 시간: 1360ms + * 메모리: 79808KB + * 언어: JAVA8 + */ +package Platinum.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class P5_2887 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static ArrayList nodeList = new ArrayList<>(); + + // * 초기 설정 + static int cost = 0; // 최소 비용 + static int[] parent; // 합집합 + + // * X좌표간의 거리, Y좌표간의 거리, Z좌표간의 거리를 기준으로 Edge는 저장하는 리스트 + static ArrayList edgeList = new ArrayList<>(); + + // * 3차원 좌표 -> X좌표간의 거리 Edge, Y좌표간의 Edge, Z좌표간의 거리 Edge + static class Edge { + int from; + int to; + int weight; + + public Edge(int from, int to, int weight) { + this.from = from; + this.to = to; + this.weight = weight; + } + } + + // ! 메인 + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + // * X, Y, Z를 중심으로 각각 3번 정렬 후 X좌표간의 거리, Y좌표간의 거리, Z좌표간의 거리를 기준으로 Edge를 만들어 edgeList에 삽입 + for (int k = 1; k <= 3; k++) { + int sortingCoordinate = k; + nodeList.sort((a, b) -> a[sortingCoordinate] - b[sortingCoordinate]); + + for (int i = 0; i < n-1; i++) { + Edge edge = new Edge(nodeList.get(i)[0], nodeList.get(i+1)[0], Math.abs(nodeList.get(i)[k] - nodeList.get(i+1)[k])); + edgeList.add(edge); + } + } + kruskal(); // * 크루스칼 알고리즘 + bw.write(String.valueOf(cost)); // * 최소비용 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 크루스칼 알고리즘 + public static void kruskal() { + int count = 0; + edgeList.sort((a, b) -> a.weight - b.weight); // * edgeList를 간선의 가중치를 기준으로 오름차순 정렬 + for (int i = 0; i < edgeList.size(); i++) { + if (count == n-1) break; // * 최소 스패닝 트리가 완성되었다면 종료 + + Edge edge = edgeList.get(i); // * 간선 선택 + if (union(edge.from, edge.to)) { // * 싸이클이 발생하지 않는다면 해당 간선을 선택하고 가중치를 cost에 더함 + count++; + cost += edge.weight; + } + } + } + + // ! UNION_FIND 합집합 찾기 + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + // ! UNION_FIND 합집합 찾기 + public static boolean union(int a, int b) { + a = findParent(a); + b = findParent(b); + if (a == b) return false; + + if (a < b) parent[b] = a; + else parent[a] = b; + + return true; + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + int x = Integer.parseInt(st.nextToken()); + int y = Integer.parseInt(st.nextToken()); + int z = Integer.parseInt(st.nextToken()); + + // * [좌표번호, X좌표, Y좌표, Z좌표] + nodeList.add(new int[] {i, x, y, z}); + } + + parent = IntStream.range(0, n).toArray(); + } +} diff --git a/java/BOJ/failed/P5_2887.java b/java/BOJ/failed/P5_2887.java deleted file mode 100644 index 8d33907..0000000 --- a/java/BOJ/failed/P5_2887.java +++ /dev/null @@ -1,77 +0,0 @@ -package failed; - -import java.io.*; -import java.util.ArrayList; -import java.util.StringTokenizer; - -public class P5_2887 { - static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); - static int n; - static long cost; - static int[] parent; - static ArrayList dists = new ArrayList<>(); - static StringTokenizer st; - - public static void main(String[] args) throws IOException { - n = Integer.parseInt(br.readLine()); - int[][] arr = new int[n][3]; - parent = new int[n]; - for (int i = 0; i < n; i++) { - parent[i] = i; - } - - for (int i = 0; i < n; i++) { - st = new StringTokenizer(br.readLine()); - for (int j = 0; j < 3; j++) { - arr[i][j] = Integer.parseInt(st.nextToken()); - } - } - - for (int i = 0; i < arr.length-1; i++) { - for (int j = i+1; j < arr.length; j++) { - dists.add(new int[] {i, j, distance(arr[i], arr[j])}); - } - } - - dists.sort((a, b) -> a[2] - b[2]); - cost = kruskal(); - - System.out.println(cost); - } - - public static int distance(int[] x, int[] y) { - return Math.min(Math.min(Math.abs(x[0] - y[0]), Math.abs(x[1] - y[1])), Math.abs(x[2] - y[2])); - } - - public static long kruskal() { - long totalDistance = 0; - int count = 0; - for (int i = 0; i < dists.size(); i++) { - int[] tunnel = dists.get(i); - if (findParent(tunnel[0]) != findParent(tunnel[1])) { - union(tunnel[0], tunnel[1]); - totalDistance += tunnel[2]; - count += 1; - } - - if (count == n-1) return totalDistance; - } - return -1; - } - - public static int findParent(int node) { - if (parent[node] != node) { - parent[node] = findParent(parent[node]); - } - return parent[node]; - } - - public static void union(int a, int b) { - a = findParent(a); - b = findParent(b); - if (a < b) parent[b] = a; - else parent[a] = b; - } - -} From 7b0b8055e822ba7e8d66b1d1de1e099e9f1abb91 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 6 Aug 2022 14:56:14 +0900 Subject: [PATCH 018/163] =?UTF-8?q?[BOJ-2211-JAVA]=20=EB=84=A4=ED=8A=B8?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_2211.java | 133 ++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_2211.java diff --git a/java/BOJ/Gold/II/G2_2211.java b/java/BOJ/Gold/II/G2_2211.java new file mode 100644 index 0000000..e005e46 --- /dev/null +++ b/java/BOJ/Gold/II/G2_2211.java @@ -0,0 +1,133 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/2211 + * + * ! 제목: 네트워크 복구 + * ! 시간 제한: 2초 + * ! 메모리 제한: 192MB + * + * ! 문제 + * N(1 ≤ N ≤ 1,000)개의 컴퓨터로 구성된 네트워크가 있다. 이들 중 몇 개의 컴퓨터들은 서로 네트워크 연결이 되어 있어 서로 다른 두 컴퓨터 간 통신이 가능하도록 되어 있다. 통신을 할 때에는 서로 직접 연결되어 있는 회선을 이용할 수도 있으며, 회선과 다른 컴퓨터를 거쳐서 통신을 할 수도 있다. + * 각 컴퓨터들과 회선은 그 성능이 차이가 날 수 있다. 따라서 각각의 직접 연결되어 있는 회선을 이용해서 통신을 하는데 걸리는 시간이 서로 다를 수 있다. 심지어는 직접 연결되어 있는 회선이 오히려 더 느려서, 다른 컴퓨터를 통해서 통신을 하는 것이 더 유리할 수도 있다. 직접 연결되어 있는 회선을 사용할 경우에는 그 회선을 이용해서 통신을 하는 데 드는 시간만큼이 들게 된다. 여러 개의 회선을 거치는 경우에는 각 회선을 이용해서 통신을 하는 데 드는 시간의 합만큼의 시간이 걸리게 된다. + * 어느 날, 해커가 네트워크에 침입하였다. 네트워크의 관리자는 우선 모든 회선과 컴퓨터를 차단한 후, 해커의 공격을 막을 수 있었다. 관리자는 컴퓨터에 보안 시스템을 설치하려 하였는데, 버전 문제로 보안 시스템을 한 대의 슈퍼컴퓨터에만 설치할 수 있었다. 한 컴퓨터가 공격을 받게 되면, 네트워크를 통해 슈퍼컴퓨터에 이 사실이 전달이 되고, 그러면 슈퍼컴퓨터에서는 네트워크를 이용해서 보안 패킷을 전송하는 방식을 사용하기로 하였다. 준비를 마친 뒤, 관리자는 다시 네트워크를 복구하기로 하였다. 이때, 다음의 조건들이 만족되어야 한다. + * 해커가 다시 공격을 할 우려가 있기 때문에, 최소 개수의 회선만을 복구해야 한다. 물론, 그렇다면 아무 회선도 복구하지 않으면 되겠지만, 이럴 경우 네트워크의 사용에 지장이 생기게 된다. 따라서 네트워크를 복구한 후에 서로 다른 두 컴퓨터 간에 통신이 가능하도록 복구해야 한다. + * 네트워크를 복구해서 통신이 가능하도록 만드는 것도 중요하지만, 해커에게 공격을 받았을 때 보안 패킷을 전송하는 데 걸리는 시간도 중요한 문제가 된다. 따라서 슈퍼컴퓨터가 다른 컴퓨터들과 통신하는데 걸리는 최소 시간이, 원래의 네트워크에서 통신하는데 걸리는 최소 시간보다 커져서는 안 된다. + * 원래의 네트워크에 대한 정보가 주어졌을 때, 위의 조건을 만족하면서 네트워크를 복구하는 방법을 알아내는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 두 정수 N, M이 주어진다. 다음 M개의 줄에는 회선의 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 컴퓨터와 B번 컴퓨터가 통신 시간이 C (1 ≤ C ≤ 10)인 회선으로 연결되어 있다는 의미이다. 컴퓨터들의 번호는 1부터 N까지의 정수이며, 1번 컴퓨터는 보안 시스템을 설치할 슈퍼컴퓨터이다. 모든 통신은 완전쌍방향 방식으로 이루어지기 때문에, 한 회선으로 연결된 두 컴퓨터는 어느 방향으로도 통신할 수 있다. + * + * 4 5 -> n m + * 1 2 1 -> a b c + * 1 4 4 -> a b c + * 1 3 2 -> a b c + * 4 2 2 -> a b c + * 4 3 3 -> a b c + * + * ! 출력 + * 첫째 줄에 복구할 회선의 개수 K를 출력한다. 다음 K개의 줄에는 복구한 회선을 나타내는 두 정수 A, B를 출력한다. 이는 A번 컴퓨터와 B번 컴퓨터를 연결하던 회선을 복구한다는 의미이다. 출력은 임의의 순서대로 하며, 답이 여러 개 존재하는 경우에는 아무 것이나 하나만 출력하면 된다. + * + * 3 + * 1 2 + * 3 1 + * 4 2 + * + * ? 채점 결과 + * 시간: 792ms + * 메모리: 111MB + * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.*; + +public class G2_2211 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static HashMap> map; + + // * 초기 설정 + static int[] restored; + static int[] before; + + // ! 메인 + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + restored[1] = 0; // * 슈퍼컴퓨터 위치(1) + dijkstra(); // * 다익스트라 + + int count = 0; // * 복구한 네트워크 갯수 + StringBuffer sb = new StringBuffer(); // * 복구한 네트워크 문자열 + + // * 2부터 N번 컴퓨터까지 복구한 통신 회선을 sb에 추가 + for (int i = 2; i <= n; i++) { + if (before[i] > 0) { + count++; + sb.append(i + " " + before[i] + "\n"); + } + } + + // * 출력 + bw.write(String.valueOf(count) + "\n"); + bw.write(sb.toString()); + + // * 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 다익스트라 알고리즘 + public static void dijkstra() { + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[1] - b[1]); + pq.add(new int[] {1, 0}); + while (!pq.isEmpty()) { + int[] cur = pq.poll(); + + if (cur[1] > restored[cur[0]]) continue; + + if (map.containsKey(cur[0])) { + for (int[] next: map.get(cur[0])) { + + if (restored[next[0]] == -1 || restored[next[0]] > cur[1] + next[1]) { + pq.add(new int[] {next[0], cur[1] + next[1]}); + restored[next[0]] = cur[1] + next[1]; + before[next[0]] = cur[0]; + } + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + map = new HashMap<>(); // * 인접 리스트 + restored = new int[n+1]; // * 최단 시간 경로 + before = new int[n+1]; // * 복구된 회선을 통해 연결된 컴퓨터 번호 + + Arrays.fill(restored, -1); // * 초기화 + + // * 인접 컴퓨터 리스트 해쉬맵 + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + if (!map.containsKey(a)) map.put(a, new ArrayList<>()); + if (!map.containsKey(b)) map.put(b, new ArrayList<>()); + + map.get(a).add(new int[] {b, c}); + map.get(b).add(new int[] {a, c}); + } + } +} \ No newline at end of file From b2935034834a68bb4c12125003a0a0fae9da598f Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 7 Aug 2022 17:50:59 +0900 Subject: [PATCH 019/163] =?UTF-8?q?[BOJ-1938-JAVA]=20=ED=86=B5=EB=82=98?= =?UTF-8?q?=EB=AC=B4=20=EC=98=AE=EA=B8=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_1938.java | 196 ++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_1938.java diff --git a/java/BOJ/Gold/II/G2_1938.java b/java/BOJ/Gold/II/G2_1938.java new file mode 100644 index 0000000..f83a2e3 --- /dev/null +++ b/java/BOJ/Gold/II/G2_1938.java @@ -0,0 +1,196 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/1938 + * + * ! 제목: 통나무 옮기기 + * ! 시간 제한: 2초 + * ! 메모리 제한: 128MB + * + * ! 문제: 링크 참조 + * + * ! 입력 & 파싱 + * 첫째 줄에 주어진 평지의 한 변의 길이 N이 주어진다. (4 ≤ N ≤ 50) 주어진다. 이어서 그 지형의 정보가 0, 1, B, E로 이루어진 문자열로 주어진다. 한 줄에 입력되는 문자열의 길이는 N이며 입력 문자 사이에는 빈칸이 없다. 통나무와 최종 위치의 개수는 1개이다. + * + * 5 -> n + * B0011 -> arr[0][0] ~ arr[0][n-1] + * B0000 + * B0000 + * 11000 + * EEE00 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ! 출력 + * 첫째 줄에 최소 동작 횟수를 출력한다. 이동이 불가능하면 0만을 출력한다. + * + * 9 + * + * ? 채점 결과 + * 시간: 104ms + * 메모리: 12MB + * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.LinkedList; + +public class G2_1938 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // 파싱 + static int n; + static char[][] arr; + + // 통나무 시작위치 & 통나무 도착위치 + static int[][] log = new int[3][2]; + static int[][] end = new int[3][2]; + + // 상하좌우 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + // 방문리스트 + static int[][][] visited; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + findLog(); // * 통나무 위치 찾기 + int result = bfs(); // * BFS 수행 + + bw.write(String.valueOf(result)); // * 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static int bfs() { + LinkedList queue = new LinkedList<>(); // 큐 생성 + visited = new int[n][n][2]; // 방문리스트 초기화 + + int ver = 0; // 시작위치가 가로인지 세로인지 + if (log[0][0] - log[1][0] == 0) ver = 0; // 가로 + else ver = 1; // 세로 + + queue.add(new int[] {log[1][0], log[1][1], ver}); // 큐에 처음의 통나무 위치 삽입 + visited[log[1][0]][log[1][1]][ver] = 1; // 방문 표시 + + // BFS 수행 + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + // * 통나무가 최종 위치에 도착했다면 사용한 명령 횟수를 리턴 + if (endCheck(cur[0], cur[1], cur[2])) { + return visited[cur[0]][cur[1]][cur[2]] - 1; + } + + // * 상하좌우로 이동 할 수 있는지 체크하고 이동이 가능하다면 방문리스트에 표시하고 큐에 삽입 + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (valueCheck(nx, ny, cur[2])) { + visited[nx][ny][cur[2]] = visited[cur[0]][cur[1]][cur[2]] + 1; + queue.add(new int[] {nx, ny, cur[2]}); + } + + } + + // * 회전이 가능한지 체크하고 회전이 가능하다면 방문리스트에 표시하고 큐에 삽입 + int newVer = cur[2] == 1 ? 0 : 1; // * 세로 -> 가로, 가로 -> 세로 + + // * 회전할 때 범위가 벗어나는지(valueCheck) + 회전할 때 벌채되지 않은 나무가 있는지(turnCheck) + if (valueCheck(cur[0], cur[1], newVer) && turnCheck(cur[0], cur[1])) { + visited[cur[0]][cur[1]][newVer] = visited[cur[0]][cur[1]][cur[2]] + 1; + queue.add(new int[] {cur[0], cur[1], newVer}); + } + + } + return 0; // * 최종 위치까지 도달할 수 없다면 0을 리턴 + } + + // ! 중심을 기준으로 3x3 구역에 벌채되지 않은 나무(값이 1인)가 있는지 + public static boolean turnCheck(int x, int y) { + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + if (arr[x + i][y + j] == '1') { + return false; + } + } + } + return true; + } + + // ! 이동할 때 가로 혹은 세로에 따라 범위를 벗어나거나 벌채되지 않은 나무가 있는지 + 이미 해당 위치를 더 적은 횟수의 명령으로 방문했는지 판단하는 함수 + public static boolean valueCheck(int x, int y, int ver) { + if (ver == 1) { // * 세로일 때 + // 위: x-1, y + if (x-1 < 0 || x-1 >= n || y < 0 || y >= n || arr[x-1][y] == '1') { + return false; + } + // 중간: x, y + if (x < 0 || x >= n || y < 0 || y >= n || arr[x][y] == '1') { + return false; + } + // 아래: x+1, y + if (x+1 < 0 || x+1 >= n || y < 0 || y >= n || arr[x+1][y] == '1') { + return false; + } + } else if (ver == 0) { // * 가로일 때 + // 왼쪽: x, y-1 + if (x < 0 || x >= n || y-1 < 0 || y-1 >= n || arr[x][y-1] == '1') { + return false; + } + // 중간: x, y + if (x < 0 || x >= n || y < 0 || y >= n || arr[x][y] == '1') { + return false; + } + // 오른쪽: x, y+1 + if (x < 0 || x >= n || y+1 < 0 || y+1 >= n || arr[x][y+1] == '1') { + return false; + } + } + + // * 방문한 적이 있는지 확인 + if (visited[x][y][ver] > 0) return false; + return true; + } + + // ! 통나무가 최종 위치에 도착했는지를 판단하는 함수 + public static boolean endCheck(int x, int y, int ver) { + if (end[0][0] - end[1][0] == 0) { // 가로 + return x == end[1][0] && y == end[1][1] && ver == 0; + } else { + return x == end[1][0] && y == end[1][1] && ver == 1; + } + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new char[n][n]; + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } + + // ! 통나무의 시작 위치와 최종 위치를 찾는 함수 + public static void findLog() { + int p = 0; + int c = 0; + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (arr[i][j] == 'B') { + log[p++] = new int[] {i, j}; + } else if (arr[i][j] == 'E') { + end[c++] = new int[] {i, j}; + } + } + } + } +} \ No newline at end of file From 145b09352612449ecc3e059e4ab0a2a975de2469 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 8 Aug 2022 14:00:21 +0900 Subject: [PATCH 020/163] =?UTF-8?q?[BOJ-2933-JAVA]=20=EB=AF=B8=EB=84=A4?= =?UTF-8?q?=EB=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_2933.java | 224 ++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_2933.java diff --git a/java/BOJ/Gold/II/G2_2933.java b/java/BOJ/Gold/II/G2_2933.java new file mode 100644 index 0000000..c566634 --- /dev/null +++ b/java/BOJ/Gold/II/G2_2933.java @@ -0,0 +1,224 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/2933 + * + * ! 제목: 미네랄 + * ! 시간 제한: 1초 + * ! 메모리 제한: 128MB + * + * ! 문제 + * 창영과 상근은 한 동굴을 놓고 소유권을 주장하고 있다. 두 사람은 막대기를 서로에게 던지는 방법을 이용해 누구의 소유인지를 결정하기로 했다. 싸움은 동굴에서 벌어진다. 동굴에는 미네랄이 저장되어 있으며, 던진 막대기가 미네랄을 파괴할 수도 있다. + * 동굴은 R행 C열로 나타낼 수 있으며, R×C칸으로 이루어져 있다. 각 칸은 비어있거나 미네랄을 포함하고 있으며, 네 방향 중 하나로 인접한 미네랄이 포함된 두 칸은 같은 클러스터이다. + * 창영은 동굴의 왼쪽에 서있고, 상근은 오른쪽에 서있다. 두 사람은 턴을 번갈아가며 막대기를 던진다. 막대를 던지기 전에 던질 높이를 정해야 한다. 막대는 땅과 수평을 이루며 날아간다. + * 막대가 날아가다가 미네랄을 만나면, 그 칸에 있는 미네랄은 모두 파괴되고 막대는 그 자리에서 이동을 멈춘다. + * 미네랄이 파괴된 이후에 남은 클러스터가 분리될 수도 있다. 새롭게 생성된 클러스터가 떠 있는 경우에는 중력에 의해서 바닥으로 떨어지게 된다. 떨어지는 동안 클러스터의 모양은 변하지 않는다. 클러스터는 다른 클러스터나 땅을 만나기 전까지 게속해서 떨어진다. 클러스터는 다른 클러스터 위에 떨어질 수 있고, 그 이후에는 합쳐지게 된다. + * 동굴에 있는 미네랄의 모양과 두 사람이 던진 막대의 높이가 주어진다. 모든 막대를 던지고 난 이후에 미네랄 모양을 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫째 줄에 동굴의 크기 R과 C가 주어진다. (1 ≤ R,C ≤ 100) + * 다음 R개 줄에는 C개의 문자가 주어지며, '.'는 빈 칸, 'x'는 미네랄을 나타낸다. + * 다음 줄에는 막대를 던진 횟수 N이 주어진다. (1 ≤ N ≤ 100) + * 마지막 줄에는 막대를 던진 높이가 주어지며, 공백으로 구분되어져 있다. 모든 높이는 1과 R사이이며, 높이 1은 행렬의 가장 바닥, R은 가장 위를 의미한다. 첫 번째 막대는 왼쪽에서 오른쪽으로 던졌으며, 두 번째는 오른쪽에서 왼쪽으로, 이와 같은 식으로 번갈아가며 던진다. + * 공중에 떠 있는 미네랄 클러스터는 없으며, 두 개 또는 그 이상의 클러스터가 동시에 떨어지는 경우도 없다. 클러스터가 떨어질 때, 그 클러스터 각 열의 맨 아래 부분 중 하나가 바닥 또는 미네랄 위로 떨어지는 입력만 주어진다. + * + * 5 6 -> n m + * ...... -> arr[0][0] ~ arr[0][m-1] + * ..xx.. + * ..x... + * ..xx.. + * .xxxx. -> arr[n-1][0] ~ arr[n-1][m-1] + * 1 -> c + * 3 -> throwing[0] ~ throwing[c-1] + * + * ! 출력 + * 입력 형식과 같은 형식으로 미네랄 모양을 출력한다. + * + * ...... + * ...... + * ..xx.. + * ..xx.. + * .xxxx. + * + * ? 채점 결과 + * 시간: 144ms + * 메모리: 14MB + * 언어: JAVA8 + **/ +package Gold.II; + +import java.io.*; +import java.util.*; + +public class G2_2933 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m, c; + static char[][] arr; + static int[] throwing; + + // * 초기 설정 + static boolean[][] visited; + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + // * 막대기 던지는 단계마다 분리된 클리스터 + static ArrayList cluster; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + throwStick(); // * 번갈아가면서 막대기 던지기 + + // * 출력 + StringBuffer sb= new StringBuffer(); + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + sb.append(arr[i][j]); + } + sb.append("\n"); + } + bw.write(String.valueOf(sb.toString())); + + br.close(); + bw.flush(); + bw.close(); + } + + // ! 막대기 던지기 + public static void throwStick() { + for (int i = 0; i < throwing.length; i++) { + visited = new boolean[n][m]; + // * 막대기에 부딪힌 클러스터 찾기 + int tx = n - throwing[i]; + int ty = -1; + + if (i % 2 == 0) { + for (int j = 0; j < m; j++) { + if (arr[tx][j] == 'x') { + ty = j; + break; + } + } + } else { + for (int j = m-1; j >= 0; j--) { + if (arr[tx][j] == 'x') { + ty = j; + break; + } + } + } + + if (ty == -1) continue; // * 부딪힌 클러스터가 없다면 패스 + arr[tx][ty] = '.'; // * 해당 위치의 미네랄 부수기 + // * 바닥과 연결된 클러스터들 방문 표시 + floor(); + + // * 방문표시 안 된 클러스터들 밑바닥까지 떨구기(떨굴 때 모양 바꾸지 않기) + // * 도중에 클러스터나 바닥을 만나면 종료 + findCluster(tx, ty); + } + } + + // ! 바닥과 연결된 클러스트들을 방문표시하기 + public static void floor() { + for (int i = 0; i < m; i++) { + if (arr[n-1][i] == 'x') { + visited[n-1][i] = true; + dfs(n-1, i); + } + } + } + + // ! 일반 DFS + public static void dfs(int x, int y) { + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (0 <= nx && nx < n && 0 <= ny && ny < m && !visited[nx][ny] && arr[nx][ny] == 'x') { + visited[nx][ny] = true; + dfs(nx, ny); + } + } + } + + // ! 분리된 클러스터덩어리를 찾고 바닥으로 떨어뜨리기 + public static void findCluster(int x, int y) { + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + // * 범위 + 방문여부 + 값 체크 + if (nx < 0 || ny < 0 || nx >= n || ny >= m || visited[nx][ny] || arr[nx][ny] != 'x') continue; + + int p = 0; + cluster = new ArrayList<>(); // * 클러스터 초기화 + cluster.add(new int[] {nx, ny}); + visited[nx][ny] = true; + + while (p < cluster.size()) { + int[] cur = cluster.get(p++); + + for (int k = 0; k < 4; k++) { + int nx2 = cur[0] + dx[k]; + int ny2 = cur[1] + dy[k]; + + if (0 <= nx2 && nx2 < n && 0 <= ny2 && ny2 < m && !visited[nx2][ny2] && arr[nx2][ny2] == 'x') { + visited[nx2][ny2] = true; + cluster.add(new int[] {nx2, ny2}); + + } + } + } + + down(); // * 바닥으로 떨어뜨리기 + break; // * 클러스터가 두개 이상 한번에 떨어지지 않기 때문에 한번 떨어졌다면 종료 + } + } + + // ! 분리된 클러스터를 떨어뜨리기(중간에 클러스터를 만나거나 바닥과 닿으면 다시 원상복귀 시키고 종료) + public static void down() { + while (true) { + for (int[] cur: cluster) { + arr[cur[0]][cur[1]] = '.'; + } + + for (int[] cur: cluster) { + if (cur[0]+1 == n || arr[cur[0]+1][cur[1]] == 'x') { + for (int[] cur2: cluster) { + arr[cur2[0]][cur2[1]] = 'x'; + } + return; + } + } + + for (int[] cur: cluster) { + arr[cur[0]+1][cur[1]] = 'x'; + cur[0] += 1; + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new char[n][m]; + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + + c = Integer.parseInt(br.readLine()); + throwing = new int[c]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < c; i++) { + throwing[i] = Integer.parseInt(st.nextToken()); + } + } +} From 709ea213ad28a09a925664f0c717c8194ac1ff5c Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 9 Aug 2022 13:16:04 +0900 Subject: [PATCH 021/163] =?UTF-8?q?[BOJ-11266-JAVA]=20=EB=8B=A8=EC=A0=88?= =?UTF-8?q?=EC=A0=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Platinum/IV/P4_11266.java | 151 +++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 java/BOJ/Platinum/IV/P4_11266.java diff --git a/java/BOJ/Platinum/IV/P4_11266.java b/java/BOJ/Platinum/IV/P4_11266.java new file mode 100644 index 0000000..4a92e79 --- /dev/null +++ b/java/BOJ/Platinum/IV/P4_11266.java @@ -0,0 +1,151 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? address: https://www.acmicpc.net/problem/11266 + * + * ! 제목: 단절점 + * ! 시간 제한: 1초 + * ! 메모리 제한: 256MB + * + * ! 문제 + * 그래프가 주어졌을 때, 단절점을 모두 구해 출력하는 프로그램을 작성하시오. + * 단절점이란 그 정점을 제거했을 때, 그래프가 두 개 또는 그 이상으로 나누어지는 정점을 말한다. 즉, 제거했을 때 그래프의 connected component의 개수가 증가하는 정점을 말한다. + * + * ! 입력 & 파싱 + * 첫째 줄에 두 정수 V(1≤V≤10,000), E(1≤E≤100,000)가 주어진다. 이는 그래프가 V개의 정점과 E개의 간선으로 이루어져 있다는 의미이다. 다음 E개의 줄에는 간선에 대한 정보를 나타내는 두 정수 A, B가 주어진다. 이는 A번 정점과 B번 정점이 연결되어 있다는 의미이며, 방향은 양방향이다. + * 입력으로 주어지는 그래프는 연결 그래프가 아닐 수도 있다. 정점은 1부터 V까지 번호가 매겨져 있다. + * + * 7 7 -> v e + * 1 4 -> a b + * 4 5 -> a b + * 5 1 -> a b + * 1 6 -> a b + * 6 7 -> a b + * 2 7 -> a b + * 7 3 -> a b + * + * ! 출력 + * 첫째 줄에 단절점의 개수를 출력한다. + * 둘째 줄에는 단절점의 번호를 공백으로 구분해 오름차순으로 출력한다. + * + * 3 + * 1 6 7 + * + * ! 채점 결과 + * ? 시간: 404ms + * ? 메모리: 46MB + * ? 언어: JAVA8 + */ +package Platinum.IV; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +public class P4_11266 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int v, e; + static ArrayList[] adj; + + // * 초기 설정 + static int sequence = 0; + static int[] visited; + static boolean[] cut; + + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + + // * 1부터 V까지 방문한 적이 없는 노드를 루트노드로 취급하고 DFS 수행 + for (int i = 1; i <= v; i++) { + if (visited[i] == 0) { + dfs(i, true); + } + } + + // * 단절점의 개수와 번호 출력 + int count = 0; + StringBuffer sb = new StringBuffer(); + + for (int i = 1; i <= v; i++) { + if (cut[i]) { + count++; + sb.append(i + " "); + } + } + + bw.write(String.valueOf(count) + "\n"); + if (count > 0) { + bw.write(sb.toString()); + } + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! DFS + public static int dfs(int cur, boolean start) { + visited[cur] = ++sequence; // DFS 순서 저장 + int ret = visited[cur]; // 도달할 수 있는 노드 중 DFS 방문 순서가 가장 작은 횟수 + int child = 0; // 자식 개수 (연결된 노드중에 이미 visited값이 0이 아니면 자식이 아니라 부모임) + + // 현재 노드와 연결된 인접 노드들에 대하여 + for (int i = 0; i < adj[cur].size(); i++) { + int next = adj[cur].get(i); // 인접 노드 + + // 이미 visited값이 0이 아니라면 부모 노드인 것 + if (visited[next] > 0) { + ret = Math.min(ret, visited[next]); // DFS 방문 순서 번호 업데이트 + continue; + } + + child++; // 자식 노드 개수 추가 + int prev = dfs(next, false); // 자식 노드가 방문할 수 있는 노드 중 DFS 방문 순서가 작은 값(재귀) + + // 루트노드가 아니면서 자식 노드가 방문할 수 있는 노드 중 DFS 방문 순서가 + // 현재 노드의 DFS 방문 순서보다 크거나 같다면 단절점 + if (!start && prev >= visited[cur]) { + cut[cur] = true; + } + + // DFS 방문 순서 번호 업데이트 + ret = Math.min(ret, prev); + } + + // 루트라면 자식노드가 2개 이상일 때 단절점 + if (start) { + cut[cur] = child >= 2; + } + + // 도달할 수 있는 노드 중 DFS 방문 순서가 가장 작은 값 리턴 + return ret; + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + v = Integer.parseInt(st.nextToken()); + e = Integer.parseInt(st.nextToken()); + + adj = new ArrayList[v+1]; + for (int i = 1; i <= v; i++) { + adj[i] = new ArrayList<>(); + } + + for (int i = 0; i < e; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + adj[a].add(b); + adj[b].add(a); + } + + visited = new int[v+1]; + cut = new boolean[v+1]; + } +} From 74da92735d5face2ba7020983adfb9a0b226ddf2 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 10 Aug 2022 13:24:14 +0900 Subject: [PATCH 022/163] =?UTF-8?q?[BOJ-13459-JAVA]=20=EA=B5=AC=EC=8A=AC?= =?UTF-8?q?=ED=83=88=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_13459.java | 182 +++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_13459.java diff --git a/java/BOJ/Gold/II/G2_13459.java b/java/BOJ/Gold/II/G2_13459.java new file mode 100644 index 0000000..66073e1 --- /dev/null +++ b/java/BOJ/Gold/II/G2_13459.java @@ -0,0 +1,182 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/13459 + * + * ! 제목: 구슬 탈출 + * ! 시간 제한: 2초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 스타트링크에서 판매하는 어린이용 장난감 중에서 가장 인기가 많은 제품은 구슬 탈출이다. 구슬 탈출은 직사각형 보드에 빨간 구슬과 파란 구슬을 하나씩 넣은 다음, 빨간 구슬을 구멍을 통해 빼내는 게임이다. + * 보드의 세로 크기는 N, 가로 크기는 M이고, 편의상 1×1크기의 칸으로 나누어져 있다. 가장 바깥 행과 열은 모두 막혀져 있고, 보드에는 구멍이 하나 있다. 빨간 구슬과 파란 구슬의 크기는 보드에서 1×1크기의 칸을 가득 채우는 사이즈이고, 각각 하나씩 들어가 있다. 게임의 목표는 빨간 구슬을 구멍을 통해서 빼내는 것이다. 이때, 파란 구슬이 구멍에 들어가면 안 된다. + * 이때, 구슬을 손으로 건드릴 수는 없고, 중력을 이용해서 이리 저리 굴려야 한다. 왼쪽으로 기울이기, 오른쪽으로 기울이기, 위쪽으로 기울이기, 아래쪽으로 기울이기와 같은 네 가지 동작이 가능하다. + * 각각의 동작에서 공은 동시에 움직인다. 빨간 구슬이 구멍에 빠지면 성공이지만, 파란 구슬이 구멍에 빠지면 실패이다. 빨간 구슬과 파란 구슬이 동시에 구멍에 빠져도 실패이다. 빨간 구슬과 파란 구슬은 동시에 같은 칸에 있을 수 없다. 또, 빨간 구슬과 파란 구슬의 크기는 한 칸을 모두 차지한다. 기울이는 동작을 그만하는 것은 더 이상 구슬이 움직이지 않을 때 까지이다. + * 보드의 상태가 주어졌을 때, 10번 이하로 빨간 구슬을 구멍을 통해 빼낼 수 있는지 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B' 로 이루어져 있다. '.'은 빈 칸을 의미하고, '#'은 공이 이동할 수 없는 장애물 또는 벽을 의미하며, 'O'는 구멍의 위치를 의미한다. 'R'은 빨간 구슬의 위치, 'B'는 파란 구슬의 위치이다. + * 입력되는 모든 보드의 가장자리에는 모두 '#'이 있다. 구멍의 개수는 한 개 이며, 빨간 구슬과 파란 구슬은 항상 1개가 주어진다. + * + * 5 5 -> n m + * ##### -> arr[0][0] ~ arr[0][m-1] + * #..B# + * #.#.# + * #RO.# + * ##### -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ! 출력 + * 파란 구슬을 구멍에 넣지 않으면서 빨간 구슬을 10번 이하로 움직여서 빼낼 수 있으면 1을 없으면 0을 출력한다. + * + * 1 + * + * ! 채점 결과 + * ? 시간: 80ms + * ? 메모리: 118MB + * ? 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.LinkedList; +import java.util.Queue; + +public class G2_13459 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + 빨간구슬 + 파란구슬 + 구멍 위치 + static int n, m; + static int[] red, blue, hole; + static char[][] arr; + + // * 상하좌우 + static int[] dx = {-1, 1, 0, 0}; + static int[] dy = {0, 0, -1, 1}; + + // * 초기 설정 + static boolean result = false; + static boolean[][][][] visited; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 입력받기 + findBead(); // * 구슬과 구멍 위치 찾기 + bfs(); // * BFS 수행 + + bw.write(String.valueOf(result ? 1 : 0)); // * 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {red[0], red[1], blue[0], blue[1], 0}); // 큐에 삽입 + visited[red[0]][red[1]][blue[0]][blue[1]] = true; // 빨간구슬 파란구슬 위치 방문표시 + + // BFS 수행 + while (!queue.isEmpty()) { + int[] cur = queue.poll(); // [빨간구슬행, 빨간구슬열, 파란구슬행, 파란구슬열, 움직인횟수] + int count = cur[4]; // 움직인 횟수 + + // 파란구슬이 구멍에 빠졌으면 패스 + if (holeCheck(cur[2], cur[3])) { + continue; + } else { + // 파란구슬이 빠지지 않았으면서 빨간구슬이 구멍에 빠졌으면 성공 및 종료 + if (holeCheck(cur[0], cur[1])) { + result = true; + break; + } + } + + if (count == 11) break; // 이동횟수가 11이 된 시점에서 모두 종료 + + for (int i = 0; i < 4; i++) { + int[] next = move(cur, i); // * 상하좌우로 기울이기 + + // 기울여서 생긴 위치가 한번도 나온적이 없다면 방문표시 후 큐에 삽입 + if (!visited[next[0]][next[1]][next[2]][next[3]]) { + visited[next[0]][next[1]][next[2]][next[3]] = true; + queue.add(new int[] {next[0], next[1], next[2], next[3], count+1}); + } + } + } + } + + // ! 구멍에 빠졌는지 체크하는 함수 + public static boolean holeCheck(int x, int y) { + if (x == hole[0] && y == hole[1]) { + return true; + } + return false; + } + + // ! 기울여서 빨간구슬과 파란구슬을 움직이는 함수 - 0(상) 1(하) 2(좌) 3(우) + public static int[] move(int[] cur, int dir) { + int[] red = new int[] {cur[0], cur[1]}; // 빨간 구슬 위치 + int[] blue = new int[] {cur[2], cur[3]}; // 파란 구슬 위치 + + // * dir(0~3)에 따라 움직이는 다음 위치가 아래 조건을 만족할 때 + // * (다음이 .[갈 수 있는 위치] 이면서) && (현재 위치가 구멍이 아니면서) && (다음으로 가는게 구멍에 빠지지 않은 상태의 블루랑 겹치지 않는 경우) + // * 빨간구슬 조건 || 파란구슬 조건 + while ((arr[red[0] + dx[dir]][red[1] + dy[dir]] == '.' && !(red[0] == hole[0] && red[1] == hole[1]) && !(!(blue[0] == hole[0] && blue[1] == hole[1]) && red[0] + dx[dir] == blue[0] && red[1] + dy[dir] == blue[1])) + || + (arr[blue[0] + dx[dir]][blue[1] + dy[dir]] == '.' && !(blue[0] == hole[0] && blue[1] == hole[1]) && !(!(red[0] == hole[0] && red[1] == hole[1]) && blue[0] + dx[dir] == red[0] && blue[1] + dy[dir] == red[1]))) { + + // * 위 while문의 빨간구슬 조건을 만족할 때 빨간구슬 이동 + if (arr[red[0] + dx[dir]][red[1] + dy[dir]] == '.' + && !(red[0] == hole[0] && red[1] == hole[1]) + && !(!(blue[0] == hole[0] && blue[1] == hole[1]) && red[0] + dx[dir] == blue[0] && red[1] + dy[dir] == blue[1])) { + red[0] += dx[dir]; + red[1] += dy[dir]; + } + + // * 위 while문의 파란구슬 조건을 만족할 때 파란구슬 이동 + if (arr[blue[0] + dx[dir]][blue[1] + dy[dir]] == '.' + && !(blue[0] == hole[0] && blue[1] == hole[1]) + && !(!(red[0] == hole[0] && red[1] == hole[1]) && blue[0] + dx[dir] == red[0] && blue[1] + dy[dir] == red[1])) { + blue[0] += dx[dir]; + blue[1] += dy[dir]; + } + } + + // * 최종 위치 리턴 + return new int[] {red[0], red[1], blue[0], blue[1]}; + } + + // ! 빨간구슬, 파란구슬, 구멍 위치 찾기 + public static void findBead() { + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (arr[i][j] == 'R') { + red = new int[] {i, j}; + arr[i][j] = '.'; + } else if (arr[i][j] == 'B') { + blue = new int[] {i, j}; + arr[i][j] = '.'; + } else if (arr[i][j] == 'O') { + hole = new int[] {i, j}; + arr[i][j] = '.'; + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + String[] s = br.readLine().split(" "); + n = Integer.parseInt(s[0]); + m = Integer.parseInt(s[1]); + + arr = new char[n][m]; + visited = new boolean[n][m][n][m]; + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } +} From d328d67dba293cf99437724ae69be1026ac6347f Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 10 Aug 2022 13:24:35 +0900 Subject: [PATCH 023/163] =?UTF-8?q?[BOJ-13460-JAVA]=20=EA=B5=AC=EC=8A=AC?= =?UTF-8?q?=ED=83=88=EC=B6=9C2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_13460.java | 177 ++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 java/BOJ/Gold/I/G1_13460.java diff --git a/java/BOJ/Gold/I/G1_13460.java b/java/BOJ/Gold/I/G1_13460.java new file mode 100644 index 0000000..d6a520f --- /dev/null +++ b/java/BOJ/Gold/I/G1_13460.java @@ -0,0 +1,177 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/13459 + * + * ! 제목: 구슬 탈출 + * ! 시간 제한: 2초 + * ! 메모리 제한: 512MB + * + * ! 문제 + * 스타트링크에서 판매하는 어린이용 장난감 중에서 가장 인기가 많은 제품은 구슬 탈출이다. 구슬 탈출은 직사각형 보드에 빨간 구슬과 파란 구슬을 하나씩 넣은 다음, 빨간 구슬을 구멍을 통해 빼내는 게임이다. + * 보드의 세로 크기는 N, 가로 크기는 M이고, 편의상 1×1크기의 칸으로 나누어져 있다. 가장 바깥 행과 열은 모두 막혀져 있고, 보드에는 구멍이 하나 있다. 빨간 구슬과 파란 구슬의 크기는 보드에서 1×1크기의 칸을 가득 채우는 사이즈이고, 각각 하나씩 들어가 있다. 게임의 목표는 빨간 구슬을 구멍을 통해서 빼내는 것이다. 이때, 파란 구슬이 구멍에 들어가면 안 된다. + * 이때, 구슬을 손으로 건드릴 수는 없고, 중력을 이용해서 이리 저리 굴려야 한다. 왼쪽으로 기울이기, 오른쪽으로 기울이기, 위쪽으로 기울이기, 아래쪽으로 기울이기와 같은 네 가지 동작이 가능하다. + * 각각의 동작에서 공은 동시에 움직인다. 빨간 구슬이 구멍에 빠지면 성공이지만, 파란 구슬이 구멍에 빠지면 실패이다. 빨간 구슬과 파란 구슬이 동시에 구멍에 빠져도 실패이다. 빨간 구슬과 파란 구슬은 동시에 같은 칸에 있을 수 없다. 또, 빨간 구슬과 파란 구슬의 크기는 한 칸을 모두 차지한다. 기울이는 동작을 그만하는 것은 더 이상 구슬이 움직이지 않을 때 까지이다. + * 보드의 상태가 주어졌을 때, 최소 몇 번 만에 빨간 구슬을 구멍을 통해 빼낼 수 있는지 구하는 프로그램을 작성하시오. + * + * ! 입력 & 파싱 + * 첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B' 로 이루어져 있다. '.'은 빈 칸을 의미하고, '#'은 공이 이동할 수 없는 장애물 또는 벽을 의미하며, 'O'는 구멍의 위치를 의미한다. 'R'은 빨간 구슬의 위치, 'B'는 파란 구슬의 위치이다. + * 입력되는 모든 보드의 가장자리에는 모두 '#'이 있다. 구멍의 개수는 한 개 이며, 빨간 구슬과 파란 구슬은 항상 1개가 주어진다. + * + * 5 5 -> n m + * ##### -> arr[0][0] ~ arr[0][m-1] + * #..B# + * #.#.# + * #RO.# + * ##### -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ! 출력 + * 최소 몇 번 만에 빨간 구슬을 구멍을 통해 빼낼 수 있는지 출력한다. 만약, 10번 이하로 움직여서 빨간 구슬을 구멍을 통해 빼낼 수 없으면 -1을 출력한다. + * + * 1 + */ +package Gold.I; + +import java.io.*; +import java.util.LinkedList; +import java.util.Queue; + +public class G1_13460 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + 빨간구슬 + 파란구슬 + 구멍 위치 + static int n, m; + static int[] red, blue, hole; + static char[][] arr; + + // * 상하좌우 + static int[] dx = {-1, 1, 0, 0}; + static int[] dy = {0, 0, -1, 1}; + + // * 초기 설정 + static int result = -1; + static boolean[][][][] visited; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 입력받기 + findBead(); // * 구슬과 구멍 위치 찾기 + bfs(); // * BFS 수행 + + bw.write(String.valueOf(result)); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {red[0], red[1], blue[0], blue[1], 0}); // 큐에 삽입 + visited[red[0]][red[1]][blue[0]][blue[1]] = true; // 빨간구슬 파란구슬 위치 방문표시 + + // BFS 수행 + while (!queue.isEmpty()) { + int[] cur = queue.poll(); // [빨간구슬행, 빨간구슬열, 파란구슬행, 파란구슬열, 움직인횟수] + int count = cur[4]; // 움직인 횟수 + + // 파란구슬이 구멍에 빠졌으면 패스 + if (holeCheck(cur[2], cur[3])) { + continue; + } else { + // 파란구슬이 빠지지 않았으면서 빨간구슬이 구멍에 빠졌으면 성공 및 종료 + if (holeCheck(cur[0], cur[1])) { + result = count; + break; + } + } + + if (count == 11) break; // 이동횟수가 11이 된 시점에서 모두 종료 + + for (int i = 0; i < 4; i++) { + int[] next = move(cur, i); // * 상하좌우로 기울이기 + + // 기울여서 생긴 위치가 한번도 나온적이 없다면 방문표시 후 큐에 삽입 + if (!visited[next[0]][next[1]][next[2]][next[3]]) { + visited[next[0]][next[1]][next[2]][next[3]] = true; + queue.add(new int[] {next[0], next[1], next[2], next[3], count+1}); + } + } + } + } + + // ! 구멍에 빠졌는지 체크하는 함수 + public static boolean holeCheck(int x, int y) { + if (x == hole[0] && y == hole[1]) { + return true; + } + return false; + } + + // ! 기울여서 빨간구슬과 파란구슬을 움직이는 함수 - 0(상) 1(하) 2(좌) 3(우) + public static int[] move(int[] cur, int dir) { + int[] red = new int[] {cur[0], cur[1]}; // 빨간 구슬 위치 + int[] blue = new int[] {cur[2], cur[3]}; // 파란 구슬 위치 + + // * dir(0~3)에 따라 움직이는 다음 위치가 아래 조건을 만족할 때 + // * (다음이 .[갈 수 있는 위치] 이면서) && (현재 위치가 구멍이 아니면서) && (다음으로 가는게 구멍에 빠지지 않은 상태의 블루랑 겹치지 않는 경우) + // * 빨간구슬 조건 || 파란구슬 조건 + while ((arr[red[0] + dx[dir]][red[1] + dy[dir]] == '.' && !(red[0] == hole[0] && red[1] == hole[1]) && !(!(blue[0] == hole[0] && blue[1] == hole[1]) && red[0] + dx[dir] == blue[0] && red[1] + dy[dir] == blue[1])) + || + (arr[blue[0] + dx[dir]][blue[1] + dy[dir]] == '.' && !(blue[0] == hole[0] && blue[1] == hole[1]) && !(!(red[0] == hole[0] && red[1] == hole[1]) && blue[0] + dx[dir] == red[0] && blue[1] + dy[dir] == red[1]))) { + + // * 위 while문의 빨간구슬 조건을 만족할 때 빨간구슬 이동 + if (arr[red[0] + dx[dir]][red[1] + dy[dir]] == '.' + && !(red[0] == hole[0] && red[1] == hole[1]) + && !(!(blue[0] == hole[0] && blue[1] == hole[1]) && red[0] + dx[dir] == blue[0] && red[1] + dy[dir] == blue[1])) { + red[0] += dx[dir]; + red[1] += dy[dir]; + } + + // * 위 while문의 파란구슬 조건을 만족할 때 파란구슬 이동 + if (arr[blue[0] + dx[dir]][blue[1] + dy[dir]] == '.' + && !(blue[0] == hole[0] && blue[1] == hole[1]) + && !(!(red[0] == hole[0] && red[1] == hole[1]) && blue[0] + dx[dir] == red[0] && blue[1] + dy[dir] == red[1])) { + blue[0] += dx[dir]; + blue[1] += dy[dir]; + } + } + + // * 최종 위치 리턴 + return new int[] {red[0], red[1], blue[0], blue[1]}; + } + + // ! 빨간구슬, 파란구슬, 구멍 위치 찾기 + public static void findBead() { + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (arr[i][j] == 'R') { + red = new int[] {i, j}; + arr[i][j] = '.'; + } else if (arr[i][j] == 'B') { + blue = new int[] {i, j}; + arr[i][j] = '.'; + } else if (arr[i][j] == 'O') { + hole = new int[] {i, j}; + arr[i][j] = '.'; + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + String[] s = br.readLine().split(" "); + n = Integer.parseInt(s[0]); + m = Integer.parseInt(s[1]); + + arr = new char[n][m]; + visited = new boolean[n][m][n][m]; + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } +} From 8ab02c51c72e0db690e3574710739fa881b337df Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 11 Aug 2022 12:31:23 +0900 Subject: [PATCH 024/163] =?UTF-8?q?[BOJ-16954-JAVA]=20=EC=9B=80=EC=A7=81?= =?UTF-8?q?=EC=9D=B4=EB=8A=94=20=EB=AF=B8=EB=A1=9C=20=ED=83=88=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_16954.java | 159 +++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_16954.java diff --git a/java/BOJ/Gold/IV/G4_16954.java b/java/BOJ/Gold/IV/G4_16954.java new file mode 100644 index 0000000..9eb9347 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_16954.java @@ -0,0 +1,159 @@ +/** + * ! 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16954 + * + * ! 제목: 움직이는 미로 탈출 + * ! 시간 제한: 2초 + * ! 메모리 제한: 512MB + * + * !문제 + * 욱제는 학교 숙제로 크기가 8×8인 체스판에서 탈출하는 게임을 만들었다. 체스판의 모든 칸은 빈 칸 또는 벽 중 하나이다. 욱제의 캐릭터는 가장 왼쪽 아랫 칸에 있고, 이 캐릭터는 가장 오른쪽 윗 칸으로 이동해야 한다. + * 이 게임의 특징은 벽이 움직인다는 점이다. 1초마다 모든 벽이 아래에 있는 행으로 한 칸씩 내려가고, 가장 아래에 있어서 아래에 행이 없다면 벽이 사라지게 된다. 욱제의 캐릭터는 1초에 인접한 한 칸 또는 대각선 방향으로 인접한 한 칸으로 이동하거나, 현재 위치에 서 있을 수 있다. 이동할 때는 빈 칸으로만 이동할 수 있다. + * 1초 동안 욱제의 캐릭터가 먼저 이동하고, 그 다음 벽이 이동한다. 벽이 캐릭터가 있는 칸으로 이동하면 더 이상 캐릭터는 이동할 수 없다. + * 욱제의 캐릭터가 가장 오른쪽 윗 칸으로 이동할 수 있는지 없는지 구해보자. + * + * ! 입력 & 파싱 + * 8개 줄에 걸쳐서 체스판의 상태가 주어진다. '.'은 빈 칸, '#'는 벽이다. 가장 왼쪽 아랫칸은 항상 벽이 아니다. + * + * ........ -> arr[0][0][0] ~ arr[0][0][n-1] ( n = 8 ) + * ........ + * ........ + * ........ + * ........ + * .####### + * #....... + * ........ -> arr[0][n-1][0] ~ arr[0][n-1][n-1] + * + * ! 출력 + * 욱제의 캐릭터가 가장 오른쪽 윗 칸에 도착할 수 있으면 1, 없으면 0을 출력한다. + * + * 1 + * + * ! 채점 결과 + * ? 시간: 84ms + * ? 메모리: 12MB + * ? 언어: JAVA8 + */ +package Gold.IV; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; + +public class G4_16954 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + static int n = 8; + static char[][][] arr = new char[100][n][n]; + + // * 초기 설정 + static int count; + static boolean result = false; + static ArrayList walls = new ArrayList<>(); + + // * 9가지 방향: 상, 하, 좌, 우, 좌상, 좌하, 우상, 우하, 제자리 + static int[] dx = {1, 1, 1, -1, -1, -1, 0, 0, 0}; + static int[] dy = {1, -1, 0, 1, -1, 0, 1, -1, 0}; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 입력 받기 + findWall(); // * 벽의 위치 찾기 + down(); // * 1초후부터 99초후의 벽의 위치 설정 => arr[1] ~ arr[99] + bfs(); // * BFS 수행 + + bw.write(String.valueOf(result ? 1 : 0)); // * 결과 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static void bfs() { + Queue queue = new LinkedList<>(); + boolean[][][] visited = new boolean[100][n][n]; // 초단위별 3차원 방문리스트 생성 + queue.add(new int[] {0, n-1, 0}); // 0초일 때 좌측 최하단인 [0, n-1, 0] => [시간, 행, 열] + visited[0][n-1][0] = true; // 초기위치 방문표시 + + // BFS + while (!queue.isEmpty()) { + int[] cur = queue.poll(); // 현재 위치 + + // 현재 시간의 현재 위치가 벽일 경우 패스 + if (arr[cur[0]][cur[1]][cur[2]] == '#') { + continue; + } + + // 현재 위치가 최종 위치일 경우 결과를 참으로 바꾸고 전체 종료 + if (cur[1] == 0 && cur[2] == n-1) { + result = true; + return; + } + + // 9가지 방향에 대하여 + for (int i = 0; i < 9; i++) { + int nx = cur[1] + dx[i]; + int ny = cur[2] + dy[i]; + + // * 범위체크 + 다음위치에 다음시간으로 방문한적이 있는지 체크 + 다음위치가 현재시간에 벽인지 체크 + 다음위치가 다음시간에 빈공간인지 체크 + if (0 <= nx && nx < n && 0 <= ny && ny < n && !visited[cur[0]+1][nx][ny] && arr[cur[0]][nx][ny] != '#' && arr[cur[0]+1][nx][ny] == '.') { + visited[cur[0]+1][nx][ny] = true; // 방문 표시 + queue.add(new int[] {cur[0]+1, nx, ny}); // 큐에 삽입 + } + } + + } + } + + // ! 1초후부터 99초후까지 미로의 상태를 찾는 함수 (99초후까지 넉넉하게 잡음) + public static void down() { + count = 1; + boolean canDown = true; + + for (int i = 1; i < 100; i++) { + for (int j = 0; j < n; j++) { + for (int k = 0; k < n; k++) { + arr[i][j][k] = '.'; + } + } + } + + // 미로 범위안에 있는 벽이 있을때까지 + while (canDown) { + canDown = false; + + for (int[] wall: walls) { + if (wall[0] < n-1) { + canDown = true; + wall[0]++; + arr[count][wall[0]][wall[1]] = '#'; + } + } + + count++; + } + } + + // ! 0초일 때 초기 벽의 위치를 찾는 함수 + public static void findWall() { + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (arr[0][i][j] == '#') { + walls.add(new int[] {i, j}); + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + for (int i = 0; i < n; i++) { + arr[0][i] = br.readLine().toCharArray(); + } + } +} From 115b1c9997967779c2e61f5db05a14076c03d668 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 11 Aug 2022 12:36:01 +0900 Subject: [PATCH 025/163] =?UTF-8?q?[BOJ-16954-JAVA]=20=EC=9B=80=EC=A7=81?= =?UTF-8?q?=EC=9D=B4=EB=8A=94=20=EB=AF=B8=EB=A1=9C=20=ED=83=88=EC=B6=9C(?= =?UTF-8?q?=EB=93=B1=EA=B8=89=EC=9D=98=EA=B2=AC=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EB=93=B1=EA=B8=89=20=EB=B3=80=EA=B2=BD=20G4=20->?= =?UTF-8?q?=20G3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/{IV/G4_16954.java => III/G3_16954.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename java/BOJ/Gold/{IV/G4_16954.java => III/G3_16954.java} (99%) diff --git a/java/BOJ/Gold/IV/G4_16954.java b/java/BOJ/Gold/III/G3_16954.java similarity index 99% rename from java/BOJ/Gold/IV/G4_16954.java rename to java/BOJ/Gold/III/G3_16954.java index 9eb9347..0e75259 100644 --- a/java/BOJ/Gold/IV/G4_16954.java +++ b/java/BOJ/Gold/III/G3_16954.java @@ -34,14 +34,14 @@ * ? 메모리: 12MB * ? 언어: JAVA8 */ -package Gold.IV; +package Gold.III; import java.io.*; import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; -public class G4_16954 { +public class G3_16954 { static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); From adde930e193aac43687643dba9bf0d783dae86ff Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 12 Aug 2022 16:57:19 +0900 Subject: [PATCH 026/163] =?UTF-8?q?[BOJ-4991-JAVA]=20=EB=A1=9C=EB=B4=87=20?= =?UTF-8?q?=EC=B2=AD=EC=86=8C=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_4991.java | 222 ++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_4991.java diff --git a/java/BOJ/Gold/II/G2_4991.java b/java/BOJ/Gold/II/G2_4991.java new file mode 100644 index 0000000..4196c73 --- /dev/null +++ b/java/BOJ/Gold/II/G2_4991.java @@ -0,0 +1,222 @@ +/** + * ? 문제 출처: 백준 온라인 져지 + * ? https://www.acmicpc.net/problem/4991 + * + * ? 제목: 로봇 청소기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 오늘은 직사각형 모양의 방을 로봇 청소기를 이용해 청소하려고 한다. 이 로봇 청소기는 유저가 직접 경로를 설정할 수 있다. + * 방은 크기가 1×1인 정사각형 칸으로 나누어져 있으며, 로봇 청소기의 크기도 1×1이다. 칸은 깨끗한 칸과 더러운 칸으로 나누어져 있으며, 로봇 청소기는 더러운 칸을 방문해서 깨끗한 칸으로 바꿀 수 있다. + * 일부 칸에는 가구가 놓여져 있고, 가구의 크기도 1×1이다. 로봇 청소기는 가구가 놓여진 칸으로 이동할 수 없다. + * 로봇은 한 번 움직일 때, 인접한 칸으로 이동할 수 있다. 또, 로봇은 같은 칸을 여러 번 방문할 수 있다. + * 방의 정보가 주어졌을 때, 더러운 칸을 모두 깨끗한 칸으로 만드는데 필요한 이동 횟수의 최솟값을 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 입력은 여러 개의 테스트케이스로 이루어져 있다. + * 각 테스트 케이스의 첫째 줄에는 방의 가로 크기 w와 세로 크기 h가 주어진다. (1 ≤ w, h ≤ 20) 둘째 줄부터 h개의 줄에는 방의 정보가 주어진다. 방의 정보는 4가지 문자로만 이루어져 있으며, 각 문자의 의미는 다음과 같다. + * + * [ .: 깨끗한 칸 ] + * [ *: 더러운 칸 ] + * [ x: 가구 ] + * [ o: 로봇 청소기의 시작 위치 ] + * 더러운 칸의 개수는 10개를 넘지 않으며, 로봇 청소기의 개수는 항상 하나이다. + * 입력의 마지막 줄에는 0이 두 개 주어진다. + * + * 7 5 -> m n + * ....... -> arr[0][0] ~ arr[0][m-1] + * .o...*. + * ....... + * .*...*. + * ....... -> arr[n-1][0] ~ arr[n-1][m-1] + * 15 13 -> m n + * .......x....... -> arr[0][0] ~ arr[0][m-1] + * ...o...x....*.. + * .......x....... + * .......x....... + * .......x....... + * ............... + * xxxxx.....xxxxx + * ............... + * .......x....... + * .......x....... + * .......x....... + * ..*....x....*.. + * .......x....... -> arr[n-1][0] ~ arr[n-1][m-1] + * 10 10 -> m n + * .......... -> arr[0][0] ~ arr[0][m-1] + * ..o....... + * .......... + * .......... + * .......... + * .....xxxxx + * .....x.... + * .....x.*.. + * .....x.... + * .....x.... -> arr[n-1][0] ~ arr[n-1][m-1] + * 0 0 m n + * + * ? 출력 + * 각각의 테스트 케이스마다 더러운 칸을 모두 깨끗한 칸으로 바꾸는 이동 횟수의 최솟값을 한 줄에 하나씩 출력한다. 만약, 방문할 수 없는 더러운 칸이 존재하는 경우에는 -1을 출력한다. + * + * 8 + * 49 + * -1 + * + * ? 채점 결과 + * * 시간: 512ms + * * 메모리: 19MB + * * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.*; + +public class G2_4991 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 초기 설정 + static int n, m; // 행, 열의 갯수 + static int[] robot; // 로봇청소기의 위치 + static char[][] arr; // 방 정보 + + // * 초기 설정 + static int count; // 먼지의 수 + 1 + static int minDist; // 이동 횟수의 최솟값 + static boolean[][] visited; // 방문리스트 + static int[] sequence; // 먼지를 고르는 순서(순열) + static int[][] dustNum; // 각위치의 먼지번호 + static int[][] dist; // 청소기-먼지, 먼지-먼지 사이의 최소 이동 거리 배열 + static ArrayList dusts; // 먼지의 위치 리스트 + + // * 상하좌우(인접) + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + StringBuffer sb = new StringBuffer(); // 정답 출력용 스트링버퍼 + + // * 모든 케이스마다 + while (true) { + input(); // * 1. 입력 받기 + + // * 2. 종료 시그널 + if (n == 0 && m == 0) { + break; + } + + // * 3. BFS를 이용해 청소기-먼지, 먼지-먼지사이의 모든 거리를 계산 + bfs(robot[0], robot[1]); + for (int[] dust: dusts) { + bfs(dust[0], dust[1]); + } + + // * 4. 순열을 이용하여 모든 순서에 대해 이동 거리의 최솟값을 갱신 + permutation(1, 1); + + // * 5. 해당 케이스의 결과를 스트링버퍼에 추가 + sb.append(minDist + "\n"); + } + + // * 6. 출력 + bw.write(sb.toString()); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 순열을 이용하여 먼지를 고르는 모든 순서에 대해 거리를 구하고 최솟값을 갱신하는 함수 + public static void permutation(int cnt, int flag) { + if (cnt == count) { + int distance = 0; + for (int i = 0; i < sequence.length - 1; i++) { + if (dist[sequence[i]][sequence[i+1]] == 0) { + minDist = -1; + return; + } + distance += dist[sequence[i]][sequence[i+1]]; + } + + minDist = Math.min(minDist, distance); + return; + } + + for (int i = 1; i < count; i++) { + if ((flag & (1 << i)) != 0) { + continue; + } + + sequence[cnt] = i; + permutation(cnt+1, flag | (1 << i)); + } + } + + // ! BFS를 이용하여 청소기-먼지, 먼지-먼지의 모든 거리를 구하는 함수 + public static void bfs(int x, int y) { + Queue queue = new LinkedList<>(); + queue.add(new int[] {x, y, 0}); + visited = new boolean[n][m]; + visited[x][y] = true; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + int c = cur[2]; + + // 먼지에 도착했을 때 시작 먼지 번호와 현재 도착한 먼지 번호사이의 거리를 저장 + if (arr[cur[0]][cur[1]] == '*') { + dist[dustNum[x][y]][dustNum[cur[0]][cur[1]]] = c; + } + + // 상하좌우에 대하여 + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + // 범위체크 + 방문체크 + 가구인지 체크 후 방문표시 및 큐에 삽입 + if (0 <= nx && nx < n && 0 <= ny && ny < m && !visited[nx][ny] && arr[nx][ny] != 'x') { + visited[nx][ny] = true; + queue.add(new int[] {nx, ny, c+1}); + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + m = Integer.parseInt(st.nextToken()); + n = Integer.parseInt(st.nextToken()); + + minDist = 50000; + arr = new char[n][m]; + dustNum = new int[n][m]; + visited = new boolean[n][m]; + dusts = new ArrayList<>(); + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + + count = 1; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (arr[i][j] == '*') { + dustNum[i][j] = count; + dusts.add(new int[] {i, j}); + count++; + } else if (arr[i][j] == 'o') { + robot = new int[] {i, j}; + } + } + } + dist = new int[count][count]; + sequence = new int[count]; + } +} \ No newline at end of file From 7bf27fa74d1dcee23b93ac04b61ad12c3482d68a Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 13 Aug 2022 11:45:54 +0900 Subject: [PATCH 027/163] =?UTF-8?q?[BOJ-1719-JAVA]=20=ED=83=9D=EB=B0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_1719.java | 161 +++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_1719.java diff --git a/java/BOJ/Gold/III/G3_1719.java b/java/BOJ/Gold/III/G3_1719.java new file mode 100644 index 0000000..beddfdd --- /dev/null +++ b/java/BOJ/Gold/III/G3_1719.java @@ -0,0 +1,161 @@ +/** + * ? 문제 출처: 백준 온라인 져지 + * ? https://www.acmicpc.net/problem/1719 + * + * ? 제목: 택배 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 명우기업은 2008년부터 택배 사업을 새로이 시작하기로 하였다. 우선 택배 화물을 모아서 처리하는 집하장을 몇 개 마련했지만, 택배 화물이 각 집하장들 사이를 오갈 때 어떤 경로를 거쳐야 하는지 결정하지 못했다. 어떤 경로를 거칠지 정해서, 이를 경로표로 정리하는 것이 여러분이 할 일이다. + * 예시된 그래프에서 굵게 표시된 1, 2, 3, 4, 5, 6은 집하장을 나타낸다. 정점간의 간선은 두 집하장간에 화물 이동이 가능함을 나타내며, 가중치는 이동에 걸리는 시간이다. 이로부터 얻어내야 하는 경로표는 다음과 같다. + * 경로표는 한 집하장에서 다른 집하장으로 최단경로로 화물을 이동시키기 위해 가장 먼저 거쳐야 하는 집하장을 나타낸 것이다. 예를 들어 4행 5열의 6은 4번 집하장에서 5번 집하장으로 최단 경로를 통해 가기 위해서는 제일 먼저 6번 집하장으로 이동해야 한다는 의미이다. + * 이와 같은 경로표를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 두 수 n과 m이 빈 칸을 사이에 두고 순서대로 주어진다. n은 집하장의 개수로 200이하의 자연수, m은 집하장간 경로의 개수로 10000이하의 자연수이다. 이어서 한 줄에 하나씩 집하장간 경로가 주어지는데, 두 집하장의 번호와 그 사이를 오가는데 필요한 시간이 순서대로 주어진다. 집하장의 번호들과 경로의 소요시간은 모두 1000이하의 자연수이다. + * + * 6 10 -> n m + * 1 2 2 -> a b c + * 1 3 1 -> a b c + * 2 4 5 -> a b c + * 2 5 3 -> a b c + * 2 6 7 -> a b c + * 3 4 4 -> a b c + * 3 5 6 -> a b c + * 3 6 7 -> a b c + * 4 6 4 -> a b c + * 5 6 2 -> a b c + * + * ? 출력 + * 예시된 것과 같은 형식의 경로표를 출력한다. + * + * - 2 3 3 2 2 + * 1 - 1 4 5 5 + * 1 1 - 4 5 6 + * 3 2 3 - 6 6 + * 2 2 3 6 - 6 + * 5 5 3 4 5 - + * + * ? 채점 결과 + * * 시간: 672ms + * * 메모리: 37MB + * * 언어: JAVA8 + */ +package Gold.III; + +import java.io.*; +import java.util.Arrays; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +public class G3_1719 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; // 집하장 개수 , 경로 개수 + static int[][] arr; // i -> j로 바로 가는 경로 중 최단거리 + + // * 초기 설정 : i부터 j까지 최단경로로 가기 위해 가장 먼저 지나야 하는 집하장 번호 arr[i][j] = k (최단거리: i -> k -> ... -> j) + static int[][] result; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 모든 집하장에서 다른 모든 집하장까지의 최단경로 구하는 다익스트라 알고리즘 + for (int i = 1; i <= n; i++) { + dijkstra(i); + } + + // * 3. 정답 출력 + StringBuffer sb = new StringBuffer(); + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (result[i][j] == 0) { + sb.append("- "); + } else { + sb.append(result[i][j] + " "); + } + } + sb.append("\n"); + } + + bw.write(sb.toString()); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 다익스트라 알고리즘 + public static void dijkstra(int start) { + int[] visited = new int[n+1]; // 방문리스트 겸 최단경로 + Arrays.fill(visited, 200000); // 방문리스트 값을 최댓값으로 초기화 + + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[2] - b[2]); // 소요시간 가중치에 따른 우선순위큐(최소힙) + pq.add(new int[] {start, start, 0}); // 시작 위치를 최소힙에 삽입 + visited[start] = 0; // 방문리스트에 시작위치 값을 0으로 초기화 + + // * 다익스트라 알고리즘 수행 + while (!pq.isEmpty()) { + int[] cur = pq.poll(); // * 현재 위치 [현재 집하장 번호, 가장 먼저 지나온 집하장, 도착 시간] + + // * 현재 위치에 방문한 시간이 이미 다른 위치로부터 시작돼서 방문한 시간보다 크다면 패스 + if (cur[2] > visited[cur[0]]) { + continue; + } + + // * 현재 집하장에서 갈 수 있는 다른 모든 집하장에 대하여 + for (int i = 1; i <= n; i++) { + if (arr[cur[0]][i] != 0) { // 경로가 있고 + if (visited[i] >= cur[2] + arr[cur[0]][i]) { // 기존에 도착한 시간보다 지금 도착하는 시간이 더 짧거나 같을 때 + visited[i] = cur[2] + arr[cur[0]][i]; // 방문리스트 최단경로 시간 업데이트 + + // * 최소힙에 삽입(이때, 가장 먼저 지나온 집하장이 start위치와 같다면 i(다음집하장 번호)로 변경하여 삽입 + pq.add(new int[] {i, cur[1] == start ? i : cur[1], visited[i]}); + + // * 가장 먼저 지나온 집하장이 start위치와 같다면 결과값에 result[start][다음위치] = 다음위치 + if (cur[1] == start) { + result[start][i] = i; + } else { + result[start][i] = cur[1]; + } + } + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n+1][n+1]; + result = new int[n+1][n+1]; + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + if (arr[a][b] == 0) { + arr[a][b] = c; + } else { + arr[a][b] = Math.min(arr[a][b], c); + } + + if (arr[b][a] == 0) { + arr[b][a] = c; + } else { + arr[b][a] = Math.min(arr[b][a], c); + } + } + } +} From 5bcdb56db95b69041f8035f5856d8ce4db04faeb Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 14 Aug 2022 17:05:21 +0900 Subject: [PATCH 028/163] =?UTF-8?q?[BOJ-2610-JAVA]=20=ED=9A=8C=EC=9D=98?= =?UTF-8?q?=EC=A4=80=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_2610.java | 210 ++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_2610.java diff --git a/java/BOJ/Gold/II/G2_2610.java b/java/BOJ/Gold/II/G2_2610.java new file mode 100644 index 0000000..7777640 --- /dev/null +++ b/java/BOJ/Gold/II/G2_2610.java @@ -0,0 +1,210 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2610 + * + * ? 제목: 회의 준비 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * KOI 준비를 위해 회의를 개최하려 한다. 주최측에서는 회의에 참석하는 사람의 수와 참석자들 사이의 관계를 따져 하나 이상의 위원회를 구성하려고 한다. 위원회를 구성하는 방식은 다음과 같다. + * 서로 알고 있는 사람은 반드시 같은 위원회에 속해야 한다. + * 효율적인 회의 진행을 위해 위원회의 수는 최대가 되어야 한다. + * 이런 방식으로 위원회를 구성한 후에 각 위원회의 대표를 한 명씩 뽑아야 한다. 각 위원회의 대표만이 회의 시간 중 발언권을 가지며, 따라서 회의 참석자들이 자신의 의견을 말하기 위해서는 자신이 속한 위원회의 대표에게 자신의 의견을 전달해야 한다. 그런데 각 참석자는 자신이 알고 있는 사람에게만 의견을 전달할 수 있어 대표에게 의견을 전달하기 위해서는 때로 여러 사람을 거쳐야 한다. 대표에게 의견을 전달하는 경로가 여러 개 있을 경우에는 가장 적은 사람을 거치는 경로로 의견을 전달하며 이때 거치는 사람의 수를 참석자의 의사전달시간이라고 한다. + * 위원회에서 모든 참석자들의 의사전달시간 중 최댓값이 최소가 되도록 대표를 정하는 프로그램을 작성하시오. + * 예를 들어 1번, 2번, 3번 세 사람으로 구성되어 있는 위원회에서 1번과 2번, 2번과 3번이 서로 알고 있다고 하자. 1번이 대표가 되면 3번이 대표인 1번에게 의견을 전달하기 위해서 2번을 거쳐야만 한다. 반대로 3번이 대표가 되어도 1번이 대표인 3번에게 의견을 전달하려면 2번을 거쳐야만 한다. 하지만 2번이 대표가 되면 1번과 3번 둘 다 아무도 거치지 않고 대표에게 직접 의견을 전달 할 수 있다. 따라서 이와 같은 경우 2번이 대표가 되어야 한다. + * + * ? 입력 & 파싱 + * 첫째 중에 회의에 참석하는 사람의 수 N이 주어진다. 참석자들은 1부터 N까지의 자연수로 표현되며 회의에 참석하는 인원은 100 이하이다. 둘째 줄에는 서로 알고 있는 관계의 수 M이 주어진다. 이어 M개의 각 줄에는 서로 아는 사이인 참석자를 나타내는 두개의 자연수가 주어진다. + * + * 8 -> n + * 7 -> m + * 1 2 -> a b + * 2 3 -> a b + * 4 5 -> a b + * 5 6 -> a b + * 4 6 -> a b + * 6 7 -> a b + * 7 4 -> a b + * + * ? 출력 + * 첫째 줄에는 구성되는 위원회의 수 K를 출력한다. 다음 K줄에는 각 위원회의 대표 번호를 작은 수부터 차례로 한 줄에 하나씩 출력한다. 한 위원회의 대표가 될 수 있는 사람이 둘 이상일 경우 그중 한 명만 출력하면 된다. + * + * 3 + * 2 + * 4 + * 8 + * + * ? 채점 결과 + * * 시간: 300ms + * * 메모리: 20MB + * * 언어: JAVA8 + * +*/ +package Gold.II; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G2_2610 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; // 사람수, 서로 알고있는 라인 수 + static int[][] arr; // 연결된 사람까지의 거리 + + // * 초기 설정 + static int[] parent; // 합집합 + static int[] result; // 결과 + static HashMap> map = new HashMap<>(); // 위원회번호(키) : 위원회에 속한 사람 리스트(값) + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + floyd(); // * 2. 플로이드-와샬 + + // * 3. 경로가 있는 사람들끼리 UNION_FIND(합집합 찾기) + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (arr[i][j] != 200 && parent[i] != parent[j]) { + union(i, j); + } + } + } + + // * 4. 대표 찾기 + find(); + + // * 5. 대표 번호 정렬하기 + Arrays.sort(result); + + // * 6. 정답 출력 + StringBuffer sb = new StringBuffer(); + sb.append(result.length + "\n"); + + for (int r : result) { + sb.append(r + "\n"); + } + + bw.write(sb.toString()); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 대표 찾기 + public static void find() { + // * 모든 사람에 대해 + for (int i = 1; i <= n; i++) { + // * 해당 그룹 번호에 맞는 위원회가 map에 등록안되어있으면 등록 + if (!map.containsKey(parent[i])) { + map.put(parent[i], new ArrayList()); + } + // * 해당 그룹 번호에 맞는 위원회에 현재 인원의 번호 추가 + map.get(parent[i]).add(i); + } + + // * 각 위원회마다 대표를 result에 저장 + int p = 0; + result = new int[map.size()]; + + for (int key : map.keySet()) { + int min = 1000; + int min_node = 0; + + for (int node : map.get(key)) { + int len = findMaxLenth(node); + if (len < min) { + min = len; + min_node = node; + } + } + + result[p++] = min_node; + } + } + + // ! 현재 인원과 연결된 사람들의 거리 중 최댓값 찾기 함수 + public static int findMaxLenth(int node) { + int max = 0; + for (int i = 1; i <= n; i++) { + if (arr[node][i] != 200) { + max = Math.max(max, arr[node][i]); + } + } + return max; + } + + // ! 플로이드 와샬 함수 + public static void floyd() { + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (arr[i][j] >= arr[i][k] + arr[k][j]) { + arr[i][j] = arr[i][k] + arr[k][j]; + } + } + } + } + + for (int i = 1; i <= n; i++) { + arr[i][i] = 0; + } + } + + // ! UNION_FIND + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + // ! UNION_FIND + public static boolean union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a == b) { + return false; + } + + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + + return true; + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + m = Integer.parseInt(br.readLine()); + + arr = new int[n+1][n+1]; + parent = IntStream.range(0, n+1).toArray(); + + for (int[] a : arr) { + Arrays.fill(a, 200); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + arr[a][b] = 1; + arr[b][a] = 1; + } + } +} \ No newline at end of file From 7c1d09dbf28188f1ec14bffb1f7f0146cb350e92 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 15 Aug 2022 19:03:34 +0900 Subject: [PATCH 029/163] =?UTF-8?q?[BOJ-JAVA-16947]=20=EC=84=9C=EC=9A=B8?= =?UTF-8?q?=20=EC=A7=80=ED=95=98=EC=B2=A0=202=ED=98=B8=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_16947.java | 159 ++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_16947.java diff --git a/java/BOJ/Gold/III/G3_16947.java b/java/BOJ/Gold/III/G3_16947.java new file mode 100644 index 0000000..5058e65 --- /dev/null +++ b/java/BOJ/Gold/III/G3_16947.java @@ -0,0 +1,159 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16947 + * + * ? 제목: 서울 지하철 2호선 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 지하철 2호선에는 51개의 역이 있고, 역과 역 사이를 연결하는 구간이 51개 있다. 즉, 정점이 51개이고, 양방향 간선이 51개인 그래프로 나타낼 수 있다. 2호선은 순환선 1개와 2개의 지선으로 이루어져 있다. 한 역에서 출발해서 계속 가면 다시 출발한 역으로 돌아올 수 있는 노선을 순환선이라고 한다. 지선은 순환선에 속하는 한 역에서 시작하는 트리 형태의 노선이다. + * 두 역(정점) 사이의 거리는 지나야 하는 구간(간선)의 개수이다. 역 A와 순환선 사이의 거리는 A와 순환선에 속하는 역 사이의 거리 중 최솟값이다. + * 지하철 2호선과 같은 형태의 노선도가 주어졌을 때, 각 역과 순환선 사이의 거리를 구해보자. + * + * ? 입력 & 파싱 + * 첫째 줄에 역의 개수 N(3 ≤ N ≤ 3,000)이 주어진다. 둘째 줄부터 N개의 줄에는 역과 역을 연결하는 구간의 정보가 주어진다. 같은 구간이 여러 번 주어지는 경우는 없고, 역은 1번부터 N번까지 번호가 매겨져 있다. 임의의 두 역 사이에 경로가 항상 존재하는 노선만 입력으로 주어진다. + * + * 6 -> n + * 1 2 -> a b + * 3 4 -> a b + * 6 4 -> a b + * 2 3 -> a b + * 1 3 -> a b + * 3 5 -> a b + * + * ? 출력 + * 총 N개의 정수를 출력한다. 1번 역과 순환선 사이의 거리, 2번 역과 순환선 사이의 거리, ..., N번 역과 순환선 사이의 거리를 공백으로 구분해 출력한다. + * + * 0 0 0 1 1 2 + * + * ? 채점 결과 + * * 시간: 608ms + * * 메모리: 236MB + * * 언어: JAVA8 +*/ +package Gold.III; + +import java.io.*; +import java.util.*; + +public class G3_16947 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static ArrayList[] arr; + + // * 초기 설정 + static boolean isCycle = false; // 사이클이 발생했는지 + static int cycleStart, cycleEnd; // 사이클 시작점, 사이클 종료점 + static boolean[] cycleVisited; // 사이클 확인 DFS를 위한 방문 리스트 + static int[] before; // 사이클 루트를 확인하기 위한 이전 노드 arr[cur] = prev + static int[] cycle; // 순환역까지의 최소거리 배열 + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + dfs(1, 1); // * 2. DFS를 이용하여 순환할때까지 탐색 + findCycle(); // * 3. 순환(사이클)이 발생하는 역들을 찾아내기 (before 이용) + + // * 4. 순환역에 포함되지 않은 역들은 BFS를 이용하여 순환역까지의 최소거리 찾기 + for (int i = 1; i <= n; i++) { + if (cycle[i] == -1) { + bfs(i); + } + } + + // * 5. cycle 배열 출력하기 (1번역 ~ N번역) + StringBuffer sb = new StringBuffer(); + for (int i = 1; i <= n; i++) { + sb.append(cycle[i] + " "); + } + + bw.write(sb.toString()); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! DFS + public static void dfs(int cur, int prev) { + cycleVisited[cur] = true; + before[cur] = prev; + + for (int next: arr[cur]) { + if (cycleVisited[next] && next != prev) { // * 바로 직전의 노드가 아닌 곳을 방문했는데 이미 방문한 노드일 때(사이클 발생) + if (!isCycle) { // * 이미 사이클이 발생한 적이 없다면 + cycleStart = next; // 사이클 시작점 + cycleEnd = cur; // 사이클 종료점 + isCycle = true; // 사이클이 이미 발생했다고 표시 + } + return; + } else if (!cycleVisited[next]) { // * 방문한 적이 없는 역일 때 + dfs(next, cur); // DFS 재귀 수행 + } + } + } + + // ! cycleEnd부터 cycleStart까지의 경로를 역추적해서 cycle배열에 값을 0으로 표시하는 함수 + public static void findCycle() { + while (cycleEnd != cycleStart) { + cycle[cycleEnd] = 0; + cycleEnd = before[cycleEnd]; + } + cycle[cycleEnd] = 0; + } + + // ! BFS: 순환역(cycle[순환역번호] = 0)까지의 최소거리를 구하는 함수 + public static void bfs(int start) { + Queue queue = new LinkedList<>(); + boolean[] visited = new boolean[n+1]; + queue.add(new int[] {start, 0}); + visited[start] = true; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cycle[cur[0]] == 0) { // * 순환역에 도착했다면 + cycle[start] = cur[1]; // * 현재 거리를 최소거리로 저장하고 종료 + return; + } + + for (int next: arr[cur[0]]) { + if (!visited[next]) { + visited[next] = true; + queue.add(new int[] {next, cur[1] + 1}); + } + } + } + + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new ArrayList[n+1]; + cycleVisited = new boolean[n+1]; + before = new int[n+1]; + cycle = new int[n+1]; + Arrays.fill(cycle, -1); + + for (int i = 1; i <= n; i++) { + arr[i] = new ArrayList<>(); + } + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + arr[a].add(b); + arr[b].add(a); + } + } + +} From 8514555081f2ccbe75e57d45ee5b8fee0668d2ca Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 16 Aug 2022 11:32:39 +0900 Subject: [PATCH 030/163] =?UTF-8?q?[BOJ-11780-JAVA]=20=ED=94=8C=EB=A1=9C?= =?UTF-8?q?=EC=9D=B4=EB=93=9C2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_11780.java | 200 +++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_11780.java diff --git a/java/BOJ/Gold/II/G2_11780.java b/java/BOJ/Gold/II/G2_11780.java new file mode 100644 index 0000000..79ef1a7 --- /dev/null +++ b/java/BOJ/Gold/II/G2_11780.java @@ -0,0 +1,200 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11780 + * + * ? 제목: 플로이드 2 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * n(1 ≤ n ≤ 100)개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 m(1 ≤ m ≤ 100,000)개의 버스가 있다. 각 버스는 한 번 사용할 때 필요한 비용이 있다. + * 모든 도시의 쌍 (A, B)에 대해서 도시 A에서 B로 가는데 필요한 비용의 최솟값을 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 버스의 정보는 버스의 시작 도시 a, 도착 도시 b, 한 번 타는데 필요한 비용 c로 이루어져 있다. 시작 도시와 도착 도시가 같은 경우는 없다. 비용은 100,000보다 작거나 같은 자연수이다. + * + * 5 -> n + * 14 -> m + * 1 2 2 -> a b c + * 1 3 3 -> a b c + * 1 4 1 -> a b c + * 1 5 10 -> a b c + * 2 4 2 -> a b c + * 3 4 1 -> a b c + * 3 5 1 -> a b c + * 4 5 3 -> a b c + * 3 5 10 -> a b c + * 3 1 8 -> a b c + * 1 4 2 -> a b c + * 5 1 7 -> a b c + * 3 4 2 -> a b c + * 5 2 4 -> a b c + * + * ?출력 + * 먼저, n개의 줄을 출력해야 한다. i번째 줄에 출력하는 j번째 숫자는 도시 i에서 j로 가는데 필요한 최소 비용이다. 만약, i에서 j로 갈 수 없는 경우에는 그 자리에 0을 출력한다. + * 그 다음에는 n×n개의 줄을 출력해야 한다. i×n+j번째 줄에는 도시 i에서 도시 j로 가는 최소 비용에 포함되어 있는 도시의 개수 k를 출력한다. 그 다음, 도시 i에서 도시 j로 가는 경로를 공백으로 구분해 출력한다. 이때, 도시 i와 도시 j도 출력해야 한다. 만약, i에서 j로 갈 수 없는 경우에는 0을 출력한다. + * + * 0 2 3 1 4 + * 12 0 15 2 5 + * 8 5 0 1 1 + * 10 7 13 0 3 + * 7 4 10 6 0 + * 0 + * 2 1 2 + * 2 1 3 + * 2 1 4 + * 3 1 3 5 + * 4 2 4 5 1 + * 0 + * 5 2 4 5 1 3 + * 2 2 4 + * 3 2 4 5 + * 2 3 1 + * 3 3 5 2 + * 0 + * 2 3 4 + * 2 3 5 + * 3 4 5 1 + * 3 4 5 2 + * 4 4 5 1 3 + * 0 + * 2 4 5 + * 2 5 1 + * 2 5 2 + * 3 5 1 3 + * 3 5 2 4 + * 0 + * + * ? 채점 결과 + * * 시간: 552ms + * * 메모리: 63MB + * * 언어: JAVA8 +*/ +package Gold.II; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G2_11780 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 이동 비용이 나올 수 있는 최댓값 + 1 => MAX값이면 이동할 수 없음을 뜻함 + static final int MAX = 10000001; + + // * 파싱 + static int n, m; // 도시 개수 | 버스 개수 + static int[][] arr; // i -> j 로 가는 최소 비용 배열(플로이드 와샬) + + // * 초기 설정 + static ArrayList[][] dist; // 최소 비용으로 이동 할 때 지나는 도시 배열 + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + floyd(); // * 2. 플로이드-와샬 + + // * 3. 출력 ( 최소비용 배열 출력 ) + StringBuffer sb = new StringBuffer(); + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (arr[i][j] == MAX) { // * 도착할 수 없을 때는 0을 출력 + sb.append(0 + " "); + } else { + sb.append(arr[i][j] + " "); + } + } + sb.append("\n"); + } + + // * 4. 출력 ( 최소비용으로 이동할 때의 도시 개수와 경로 출력 ) + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (arr[i][j] == 0 || arr[i][j] == MAX) { // * 자기자신에서 자기자신으로 가는 경로 혹은 도착할 수 없는 경로일 때 0 출력 + sb.append(0); + } else { + sb.append((dist[i][j].size() + 2) + " "); // * i -> j로 최소비용으로 이동했을 때 지나간 도시의 갯수(dist[i][j].size()) + 시작점,종료점(2) + sb.append(i + " "); // * 시작점 + + // * i -> j 로 최소비용으로 이동했을 때 지나는 도시가 1개라도 있을 때 해당 도시들을 공백으로 구분해서 출력 + if (dist[i][j].size() > 0) { + for (int k : dist[i][j]) { + sb.append(k + " "); + } + } + sb.append(j + " "); // * 종료점 + } + sb.append("\n"); + } + } + + bw.write(sb.toString()); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 플로이드-와샬 + public static void floyd() { + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + // * 자기 자신에서 자기 자신으로 도착하는 경로는 없기 때문에 해당 경우 패스 + if (i == k || k == j) continue; + + // * 최소비용이 갱신되는 시점에서 + if (arr[i][j] > arr[i][k] + arr[k][j]) { + arr[i][j] = arr[i][k] + arr[k][j]; // * 최소비용 갱신 + + dist[i][j] = new ArrayList<>(); // * i -> j를 최소비용으로 갈 때 지나는 도시 초기화 + dist[i][j].addAll(dist[i][k]); // * i -> k를 최소비용으로 갈 때 지나는 도시 삽입 + dist[i][j].add(k); // * k도시 삽입 + dist[i][j].addAll(dist[k][j]); // * k -> j를 최소비용으로 갈 때 지나는 도시 삽입 + } + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + m = Integer.parseInt(br.readLine()); + + arr = new int[n+1][n+1]; + for (int[] a : arr) { + Arrays.fill(a, MAX); + } + + for (int i = 1; i <= n; i++) { + arr[i][i] = 0; + } + + dist = new ArrayList[n+1][n+1]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + dist[i][j] = new ArrayList<>(); + } + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + if (arr[a][b] == MAX) { + arr[a][b] = c; + } else { + arr[a][b] = Math.min(arr[a][b], c); + } + } + } +} From 8edc51e10617b265df806e5859a0b04b67d75238 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 17 Aug 2022 09:38:30 +0900 Subject: [PATCH 031/163] =?UTF-8?q?[BOJ-14621-JAVA]=20=EB=82=98=EB=A7=8C?= =?UTF-8?q?=20=EC=95=88=EB=90=98=EB=8A=94=20=EC=97=B0=EC=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_14621.java | 150 ++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_14621.java diff --git a/java/BOJ/Gold/III/G3_14621.java b/java/BOJ/Gold/III/G3_14621.java new file mode 100644 index 0000000..568f04a --- /dev/null +++ b/java/BOJ/Gold/III/G3_14621.java @@ -0,0 +1,150 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14621 + * + * ? 제목: 나만 안되는 연애 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 깽미는 24살 모태솔로이다. 깽미는 대마법사가 될 순 없다며 자신의 프로그래밍 능력을 이용하여 미팅 어플리케이션을 만들기로 결심했다. 미팅 앱은 대학생을 타겟으로 만들어졌으며 대학교간의 도로 데이터를 수집하여 만들었다. + * 이 앱은 사용자들을 위해 사심 경로를 제공한다. 이 경로는 3가지 특징을 가지고 있다. + * 사심 경로는 사용자들의 사심을 만족시키기 위해 남초 대학교와 여초 대학교들을 연결하는 도로로만 이루어져 있다. + * 사용자들이 다양한 사람과 미팅할 수 있도록 어떤 대학교에서든 모든 대학교로 이동이 가능한 경로이다. + * 시간을 낭비하지 않고 미팅할 수 있도록 이 경로의 길이는 최단 거리가 되어야 한다. + * 만약 도로 데이터가 만약 왼쪽의 그림과 같다면, 오른쪽 그림의 보라색 선과 같이 경로를 구성하면 위의 3가지 조건을 만족하는 경로를 만들 수 있다. + * 이때, 주어지는 거리 데이터를 이용하여 사심 경로의 길이를 구해보자. + * + * ? 입력 & 파싱 + * 입력의 첫째 줄에 학교의 수 N와 학교를 연결하는 도로의 개수 M이 주어진다. (2 ≤ N ≤ 1,000) (1 ≤ M ≤ 10,000) + * 둘째 줄에 각 학교가 남초 대학교라면 M, 여초 대학교라면 W이 주어진다. + * 다음 M개의 줄에 u v d가 주어지며 u학교와 v학교가 연결되어 있으며 이 거리는 d임을 나타낸다. (1 ≤ u, v ≤ N) , (1 ≤ d ≤ 1,000) + * + * 5 7 -> n m + * M W W W M -> boys[1] ~ boys[n] + * 1 2 12 -> a, b, c + * 1 3 10 -> a, b, c + * 4 2 5 -> a, b, c + * 5 2 5 -> a, b, c + * 2 5 10 -> a, b, c + * 3 4 3 -> a, b, c + * 5 4 7 -> a, b, c + * + * ? 출력 + * 깽미가 만든 앱의 경로 길이를 출력한다. (모든 학교를 연결하는 경로가 없을 경우 -1을 출력한다.) + * + * 34 + * + * ? 채점 결과 + * * 시간: 372ms + * * 메모리: 226MB + * * 언어: JAVA8 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G3_14621 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static boolean[] boys; + static ArrayList list; + + // * 초기 설정 + static int count = 0, length = 0; + static int[] parent; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + kruskal(); // * 2. 크루스칼 알고리즘 + + // * 3. 모든 대학교가 연결됐을 때 그 경로를 출력 vs 연결 못했을 때 -1 출력 + bw.write(String.valueOf(count == n-1 ? length : -1)); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + boys = new boolean[n+1]; + int p = 1; + for (String s: br.readLine().split(" ")) { + if (s.equals("M")) { + boys[p++] = true; + } else { + boys[p++] = false; + } + } + + list = new ArrayList<>(); + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + list.add(new int[] {a, b, c}); + } + list.sort((school1, school2) -> school1[2] - school2[2]); // * 경로의 길이를 기준으로 오름차순 정렬 + parent = IntStream.range(0, n+1).toArray(); + } + + // ! 크루스칼 알고리즘 + public static void kruskal() { + for (int i = 0; i < list.size(); i++) { + if (count == n-1) { + break; + } + + int[] con = list.get(i); + if (boys[con[0]] == boys[con[1]]) { // * 남초대학 - 남초대학 | 여초대학 - 여초대학 사이의 경로는 패스 + continue; + } + + if (union(con[0], con[1])) { // * 사이클이 발생하지 않는다면 해당 경로를 선택하고 경로 길이 업데이트 + count++; + length += con[2]; + } + } + } + + // ! UNION_FIND (합집합 찾기) + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + + return parent[node]; + } + + // ! UNION_FIND (합집합 찾기) + public static boolean union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a == b) { + return false; + } + + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + return true; + } +} From c3d782df6000dac7daedcfd1dddf77b8adc7d03d Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 18 Aug 2022 14:20:09 +0900 Subject: [PATCH 032/163] =?UTF-8?q?[BOJ-2473-JAVA]=20=EC=84=B8=20=EC=9A=A9?= =?UTF-8?q?=EC=95=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_2473.java | 101 +++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_2473.java diff --git a/java/BOJ/Gold/III/G3_2473.java b/java/BOJ/Gold/III/G3_2473.java new file mode 100644 index 0000000..21ee6fe --- /dev/null +++ b/java/BOJ/Gold/III/G3_2473.java @@ -0,0 +1,101 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2473 + * + * ? 제목: 세 용액 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * KOI 부설 과학연구소에서는 많은 종류의 산성 용액과 알칼리성 용액을 보유하고 있다. 각 용액에는 그 용액의 특성을 나타내는 하나의 정수가 주어져있다. 산성 용액의 특성값은 1부터 1,000,000,000까지의 양의 정수로 나타내고, 알칼리성 용액의 특성값은 -1부터 -1,000,000,000까지의 음의 정수로 나타낸다. + * 같은 양의 세 가지 용액을 혼합한 용액의 특성값은 혼합에 사용된 각 용액의 특성값의 합으로 정의한다. 이 연구소에서는 같은 양의 세 가지 용액을 혼합하여 특성값이 0에 가장 가까운 용액을 만들려고 한다. + * 예를 들어, 주어진 용액들의 특성값이 [-2, 6, -97, -6, 98]인 경우에는 특성값이 -97와 -2인 용액과 특성값이 98인 용액을 혼합하면 특성값이 -1인 용액을 만들 수 있고, 이 용액이 특성값이 0에 가장 가까운 용액이다. 참고로, 세 종류의 알칼리성 용액만으로나 혹은 세 종류의 산성 용액만으로 특성값이 0에 가장 가까운 혼합 용액을 만드는 경우도 존재할 수 있다. + * 산성 용액과 알칼리성 용액이 주어졌을 때, 이 중 같은 양의 세 개의 서로 다른 용액을 혼합하여 특성값이 0에 가장 가까운 용액을 만들어내는 세 용액을 찾는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에는 전체 용액의 수 N이 입력된다. N은 3 이상 5,000 이하의 정수이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 수들은 모두 -1,000,000,000 이상 1,000,000,000 이하이다. N개의 용액들의 특성값은 모두 다르고, 산성 용액만으로나 알칼리성 용액만으로 입력이 주어지는 경우도 있을 수 있다. + * + * 5 -> n + * -2 6 -97 -6 98 -> arr[0] ~ arr[n-1] + * + * ? 출력 + * 첫째 줄에 특성값이 0에 가장 가까운 용액을 만들어내는 세 용액의 특성값을 출력한다. 출력해야하는 세 용액은 특성값의 오름차순으로 출력한다. 특성값이 0에 가장 가까운 용액을 만들어내는 경우가 두 개 이상일 경우에는 그 중 아무것이나 하나를 출력한다. + * + * -6 -3 -2 + * + * ? 채점 결과 + * * 시간: 168ms + * * 메모리: 14MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.III; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G3_2473 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int[] result = new int[3]; // * 0에 가장 가까운 세 용액의 특성값 + static long max = Long.MAX_VALUE; // * 세 용액의 특성값의 합의 절댓값의 최댓값 + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 투포인터를 이용하여 세 용액의 특성값의 합을 비교하여 합이 0에 가장 가까운 세 용액 찾기 + for (int i = 0; i < arr.length-2; i++) { + int base = arr[i]; // * 기준이 되는 용액 + int left = i+1; // * 기준 용액보다 특성값이 큰 용액 중 가장 특성값이 작은 용액 + int right = arr.length-1; // * 특성값이 가장 큰 용액 + + // * 투포인터 + while (left < right) { + long sum = (long) base + arr[left] + arr[right]; + + // * 0에 더 가까운 세 용액을 찾았을 때, 결과와 max값 업데이트 + if (Math.abs(sum) <= max) { + max = Math.abs(sum); + result[0] = base; + result[1] = arr[left]; + result[2] = arr[right]; + } + + // * 특성값의 합이 음수일 때 left 포인터 1증가 + if (sum < 0) { + left++; + } else { // * 특성값의 합이 양수일 때 right 포인터 1 감소 + right--; + } + + } + } + + // * 3. 결과 출력 + System.out.println(result[0] + " " + result[1] + " " + result[2]); + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new int[n]; + + int p = 0; + st = new StringTokenizer(br.readLine()); + + for (int i = 0; i < n; i++) { + arr[p++] = Integer.parseInt(st.nextToken()); + } + + // * 용액들을 특성값을 기준으로 오름차순 정렬 + Arrays.sort(arr); + } +} \ No newline at end of file From a1eed0f5a2df9712ae6a26d281f3327c144fcca9 Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 19 Aug 2022 14:19:52 +0900 Subject: [PATCH 033/163] =?UTF-8?q?[BOJ-21609-JAVA]=20=EC=83=81=EC=96=B4?= =?UTF-8?q?=20=EC=A4=91=ED=95=99=EA=B5=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_21609.java | 322 +++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_21609.java diff --git a/java/BOJ/Gold/II/G2_21609.java b/java/BOJ/Gold/II/G2_21609.java new file mode 100644 index 0000000..5dd0b58 --- /dev/null +++ b/java/BOJ/Gold/II/G2_21609.java @@ -0,0 +1,322 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/21609 + * + * ? 제목: 상어 중학교 + * ? 문제 + * 상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록이 있다. 일반 블록은 M가지 색상이 있고, 색은 M이하의 자연수로 표현한다. 검은색 블록은 -1, 무지개 블록은 0으로 표현한다. (i, j)는 격자의 i번 행, j번 열을 의미하고, |r1 - r2| + |c1 - c2| = 1을 만족하는 두 칸 (r1, c1)과 (r2, c2)를 인접한 칸이라고 한다. + * 블록 그룹은 연결된 블록의 집합이다. 그룹에는 일반 블록이 적어도 하나 있어야 하며, 일반 블록의 색은 모두 같아야 한다. 검은색 블록은 포함되면 안 되고, 무지개 블록은 얼마나 들어있든 상관없다. 그룹에 속한 블록의 개수는 2보다 크거나 같아야 하며, 임의의 한 블록에서 그룹에 속한 인접한 칸으로 이동해서 그룹에 속한 다른 모든 칸으로 이동할 수 있어야 한다. 블록 그룹의 기준 블록은 무지개 블록이 아닌 블록 중에서 행의 번호가 가장 작은 블록, 그러한 블록이 여러개면 열의 번호가 가장 작은 블록이다. + * 오늘은 이 게임에 오토 플레이 기능을 만드려고 한다. 오토 플레이는 다음과 같은 과정이 블록 그룹이 존재하는 동안 계속해서 반복되어야 한다. + * 크기가 가장 큰 블록 그룹을 찾는다. 그러한 블록 그룹이 여러 개라면 포함된 무지개 블록의 수가 가장 많은 블록 그룹, 그러한 블록도 여러개라면 기준 블록의 행이 가장 큰 것을, 그 것도 여러개이면 열이 가장 큰 것을 찾는다. + * 1에서 찾은 블록 그룹의 모든 블록을 제거한다. 블록 그룹에 포함된 블록의 수를 B라고 했을 때, B2점을 획득한다. + * 격자에 중력이 작용한다. + * 격자가 90도 반시계 방향으로 회전한다. + * 다시 격자에 중력이 작용한다. + * 격자에 중력이 작용하면 검은색 블록을 제외한 모든 블록이 행의 번호가 큰 칸으로 이동한다. 이동은 다른 블록이나 격자의 경계를 만나기 전까지 계속 된다. + * + * 다음은 N = 5, M = 3인 경우의 예시이다. + * + * 2 2 -1 3 1 + * 3 3 2 0 -1 + * 0 0 0 1 2 + * -1 3 1 3 2 + * 0 3 2 2 1 + * 여기서 찾을 수 있는 크기가 가장 큰 블록 그룹을 다음과 같이 빨간색으로 표시했다. + * + * 2 2 -1 3 1 + * 3 3 2 0 -1 + * 0 0 0 1 2 + * -1 3 1 3 2 + * 0 3 2 2 1 + * 블록 그룹이 제거되면 다음과 같이 변하고, 점수 82점을 획득한다. + * + * 2 2 -1 3 1 + * 2 0 -1 + * 1 2 + * -1 1 3 2 + * 2 2 1 + * 중력이 작용하면 다음과 같이 변한다. + * + * -1 3 1 + * 0 -1 + * 2 2 1 2 + * -1 1 3 2 + * 2 2 2 1 + * 90도 반시계방향으로 회전한 결과는 다음과 같다. + * + * 1 -1 2 2 1 + * 3 0 1 3 2 + * -1 2 1 2 + * 2 + * 2 -1 + * 다시 여기서 중력이 작용하면 다음과 같이 변한다. + * + * 1 -1 + * 3 2 2 1 + * -1 1 3 2 + * 2 1 2 + * 0 2 -1 2 + * 오토 플레이가 모두 끝났을 때 획득한 점수의 합을 구해보자. + * + * ? 입력 & 파싱 + * 첫째 줄에 격자 한 변의 크기 N, 색상의 개수 M이 주어진다. + * 둘째 줄부터 N개의 줄에 격자의 칸에 들어있는 블록의 정보가 1번 행부터 N번 행까지 순서대로 주어진다. 각 행에 대한 정보는 1열부터 N열까지 순서대로 주어진다. 입력으로 주어지는 칸의 정보는 -1, 0, M이하의 자연수로만 이루어져 있다. + * + * 5 3 -> n m + * 2 2 -1 3 1 -> arr[0][0] ~ arr[n-1] + * 3 3 2 0 -1 + * 0 0 0 1 2 + * -1 3 1 3 2 + * 0 3 2 2 1 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 첫째 줄에 획득한 점수의 합을 출력한다. + * + * 77 + * + * ? 제한 + * 1 ≤ N ≤ 20 + * 1 ≤ M ≤ 5 + * + * ? 채점 결과 + * * 시간: 272ms + * * 메모리: 20MB + * * 언어: JAVA8 + * * 시도: 4 + **/ +package Gold.II; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +public class G2_21609 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[][] arr; + + // * 초기 설정 + static int point = 0; // 최종 점수 + static boolean isFinished = false; // 끝났는지 여부 + static boolean[][] visited; // 방문리스트 + static ArrayList> groups; // 매 단계마다 가능한 모든 블록 그룹 리스트 + + // * 상하좌우 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 2개 이상의 블록을 갖는 그룹이 있을 때까지 + while (true) { + groups = new ArrayList<>(); // 그룹 리스트 초기화 + visited = new boolean[n][n]; // 방문 리스트 초기화 + + // * 2-1. 그룹 찾기 + findGroup(); + + // 존재하는 그룹이 없다면 종료 + if (isFinished) { + break; + } + + // * 2-2. 문제 조건을 만족하는 최대 길이의 블록 찾기 + ArrayList maxBlock = findMaxBlock(); + + // 문제 조건을 만족하는 블록의 최대 길이가 2보다 작을 때 종료 + if (maxBlock.size() < 2) { + break; + } + + // * 2-3. 해당 블록의 길이의 제곱만큼 점수 증가 + point += (int) Math.pow(maxBlock.size(), 2); + + // * 2-4. 해당 그룹의 블록들을 빈칸(-2) 처리 + for (int[] a: maxBlock) { + arr[a[0]][a[1]] = -2; + } + + // * 2-5. 중력 -> 반시계 회전 -> 중력 + down(); + rotateRCW(); + down(); + } + + // * 3. 점수 출력 + bw.write(String.valueOf(point)); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 기존 블록 찾기 함수 + public static int[] findBase(ArrayList list) { + for (int[] b : list) { + if (arr[b[0]][b[1]] != 0) { + return b; + } + } + return null; + } + + // ! 2차원 배열 반시계 회전 함수 + public static void rotateRCW() { + // X, Y -> N-Y-1, X + int[][] newArr = new int[n][n]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + newArr[n-j-1][i] = arr[i][j]; + } + } + + arr = newArr; + } + + // ! 중력 작용 함수 + public static void down() { + for (int j = 0; j < n; j++) { + for (int i = n-1; i >= 0; i--) { + if (arr[i][j] >= 0) { + for (int k = i+1; k < n; k++) { + if (arr[k][j] == -2) { + arr[k][j] = arr[k-1][j]; + arr[k-1][j] = -2; + } else { + break; + } + } + } + } + } + } + + // ! 조건을 만족하는 길이가 가장 큰 블록 그룹 리스트를 찾는 함수 + public static ArrayList findMaxBlock() { + int maxLength = 0; + for (int i = 0; i < groups.size(); i++) { + if (maxLength < groups.get(i).size()) { + maxLength = groups.get(i).size(); + } + } + + ArrayList maxBlock = null; + int rainbow = 0; + int baseX = 0; + int baseY = 0; + + for (int i = 0; i < groups.size(); i++) { + if (groups.get(i).size() == maxLength) { + blockSort(groups.get(i)); + int[] base = findBase(groups.get(i)); + + int count = 0; + for (int[] g: groups.get(i)) { + if (arr[g[0]][g[1]] == 0) { + count++; + } + } + + if (maxBlock == null) { + maxBlock = groups.get(i); + baseX = base[0]; + baseY = base[1]; + rainbow = count; + continue; + } + + if (rainbow < count) { + maxBlock = groups.get(i); + rainbow = count; + baseX = base[0]; + baseY = base[1]; + } else if (rainbow == count) { + if (baseX < base[0]) { + maxBlock = groups.get(i); + rainbow = count; + baseX = base[0]; + baseY = base[1]; + } else if (baseX == base[0]) { + if (baseY < base[1]) { + maxBlock = groups.get(i); + rainbow = count; + baseX = base[0]; + baseY = base[1]; + } + } + } + } + } + + return maxBlock; + } + + // ! 각 그룹의 블록의 위치를 행, 열에 대해 오름차순 + public static void blockSort(ArrayList list) { + list.sort((a, b) -> { + if (a[0] == b[0]) { + return a[1] - b[1]; + } + return a[0] - b[0]; + }); + } + + // ! DFS를 이용하여 가능한 모든 블록 그룹 리스트를 찾는 함수 + public static void findGroup() { + isFinished = true; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (arr[i][j] > 0 && !visited[i][j]) { + isFinished = false; + groups.add(new ArrayList<>()); + visited[i][j] = true; + dfs(i, j, arr[i][j]); + + for (int[] group: groups.get(groups.size()-1)) { + if (arr[group[0]][group[1]] == 0) { + visited[group[0]][group[1]] = false; + } + } + } + } + } + } + + // ! DFS 함수 + public static void dfs(int x, int y, int gNum) { + groups.get(groups.size()-1).add(new int[] {x, y}); + + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (0 <= nx && nx < n && 0 <= ny && ny < n && !visited[nx][ny] && (arr[nx][ny] == gNum || arr[nx][ny] == 0)) { + visited[nx][ny] = true; + dfs(nx, ny, gNum); + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n][n]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From aa481acf9ae66d51a6d90e02ef3535dbd112d5e9 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 20 Aug 2022 14:58:14 +0900 Subject: [PATCH 034/163] =?UTF-8?q?[BOJ-16933-JAVA]=20=EB=B2=BD=20?= =?UTF-8?q?=EB=B6=80=EC=88=98=EA=B3=A0=20=EC=9D=B4=EB=8F=99=ED=95=98?= =?UTF-8?q?=EA=B8=B0=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_16933.java | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 java/BOJ/Gold/I/G1_16933.java diff --git a/java/BOJ/Gold/I/G1_16933.java b/java/BOJ/Gold/I/G1_16933.java new file mode 100644 index 0000000..95bf8a6 --- /dev/null +++ b/java/BOJ/Gold/I/G1_16933.java @@ -0,0 +1,121 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16933 + * + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다. 이동하지 않고 같은 칸에 머물러있는 경우도 가능하다. 이 경우도 방문한 칸의 개수가 하나 늘어나는 것으로 생각해야 한다. + * 이번 문제에서는 낮과 밤이 번갈아가면서 등장한다. 가장 처음에 이동할 때는 낮이고, 한 번 이동할 때마다 낮과 밤이 바뀌게 된다. 이동하지 않고 같은 칸에 머무르는 경우에도 낮과 밤이 바뀌게 된다. + * 만약에 이동하는 도중에 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 K개 까지 부수고 이동하여도 된다. 단, 벽은 낮에만 부술 수 있다. + * 한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다. + * 맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000), K(1 ≤ K ≤ 10)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자. + * + * 1 4 1 -> n m k + * 0010 -> arr[0][0] ~ arr[0][m-1] + * + * ? 출력 + * 첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다. + * + * 5 + * + * ? 채점 결과 + * * 시간: 4708ms + * * 메모리: 700MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.I; + +import java.io.*; +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G1_16933 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m, k; + static char[][] arr; + + // * 초기 설정 + static int answer = -1; + static int[][][][] visited; + + // * 상하좌우 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0 ,0, 1, -1}; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + bfs(); // * 2. BFS + + System.out.println(answer); // * 3. 정답 출력 + + br.close(); + } + + // ! BFS + public static void bfs() { + // 낮 : 0 , 밤 : 1 + Queue queue = new ArrayDeque<>(); // ! LinkedList -> 시간초과 + queue.add(new int[] {0, 0, 0, 0}); // [X, Y, K, D] + visited[0][0][0][0] = 1; + + // ! 4차원 BFS 풀이 visited[행][열][벽을부순횟수][낮or밤] + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == n-1 && cur[1] == m-1) { + answer = visited[cur[0]][cur[1]][cur[2]][cur[3]]; + break; + } + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + continue; + } + + if (arr[nx][ny] == '1' && cur[2] < k && cur[3] == 0 && visited[nx][ny][cur[2]+1][cur[3]^1] == 0) { + visited[nx][ny][cur[2]+1][cur[3]^1] = visited[cur[0]][cur[1]][cur[2]][cur[3]] + 1; + queue.add(new int[] {nx, ny, cur[2]+1, cur[3]^1}); + } else if (arr[nx][ny] == '0') { + if (visited[nx][ny][cur[2]][cur[3]^1] == 0) { + visited[nx][ny][cur[2]][cur[3]^1] = visited[cur[0]][cur[1]][cur[2]][cur[3]] + 1; + queue.add(new int[] {nx, ny, cur[2], cur[3]^1}); + } + } + + if (visited[cur[0]][cur[1]][cur[2]][cur[3]^1] == 0) { + visited[cur[0]][cur[1]][cur[2]][cur[3]^1] = visited[cur[0]][cur[1]][cur[2]][cur[3]] + 1; + queue.add(new int[] {cur[0], cur[1], cur[2], cur[3]^1}); + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + arr = new char[n][m]; + visited = new int[n][m][k+1][2]; + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } +} From 544945637f46d9a13fb515486c23a8e43d7a72c7 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 20 Aug 2022 14:58:27 +0900 Subject: [PATCH 035/163] =?UTF-8?q?[BOJ-16933-JAVA]=20=EB=B2=BD=20?= =?UTF-8?q?=EB=B6=80=EC=88=98=EA=B3=A0=20=EC=9D=B4=EB=8F=99=ED=95=98?= =?UTF-8?q?=EA=B8=B0=203(=EC=B5=9C=EC=A0=81=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_16933_2.java | 130 ++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 java/BOJ/Gold/I/G1_16933_2.java diff --git a/java/BOJ/Gold/I/G1_16933_2.java b/java/BOJ/Gold/I/G1_16933_2.java new file mode 100644 index 0000000..f146a29 --- /dev/null +++ b/java/BOJ/Gold/I/G1_16933_2.java @@ -0,0 +1,130 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16933 + * + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다. 이동하지 않고 같은 칸에 머물러있는 경우도 가능하다. 이 경우도 방문한 칸의 개수가 하나 늘어나는 것으로 생각해야 한다. + * 이번 문제에서는 낮과 밤이 번갈아가면서 등장한다. 가장 처음에 이동할 때는 낮이고, 한 번 이동할 때마다 낮과 밤이 바뀌게 된다. 이동하지 않고 같은 칸에 머무르는 경우에도 낮과 밤이 바뀌게 된다. + * 만약에 이동하는 도중에 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 K개 까지 부수고 이동하여도 된다. 단, 벽은 낮에만 부술 수 있다. + * 한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다. + * 맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000), K(1 ≤ K ≤ 10)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자. + * + * 1 4 1 -> n m k + * 0010 -> arr[0][0] ~ arr[0][m-1] + * + * ? 출력 + * 첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다. + * + * 5 + * + * ? 채점 결과 + * * 시간: 916ms + * * 메모리: 302MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.I; + +import java.io.*; +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G1_16933_2 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m, k; + static char[][] arr; + + // * 초기 설정 + static int answer = -1; + static int[][] visited; + + // * 상하좌우 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0 ,0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + bfs(); // * 2. BFS + + // * 3. 정답 출력 + System.out.println(answer); + } + + // ! BFS + public static void bfs() { + // 낮 : 홀 , 밤 : 짝 + Queue queue = new ArrayDeque<>(); + queue.add(new int[] {0, 0, 0, 1}); // [X, Y, K, D] + visited[0][0] = 0; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == n-1 && cur[1] == m-1) { + answer = cur[3]; + break; + } + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + continue; + } + + if (visited[nx][ny] <= cur[2]) { + continue; + } + + if (arr[nx][ny] == '1') { + if (cur[2] >= k || visited[nx][ny] <= cur[2] + 1) { + continue; + } + + if (cur[3] % 2 == 0) { + queue.add(new int[] {cur[0], cur[1], cur[2], cur[3]+1}); + } else { + visited[nx][ny] = cur[2] + 1; + queue.add(new int[] {nx, ny, cur[2] + 1, cur[3] + 1}); + } + } else { + visited[nx][ny] = cur[2]; + queue.add(new int[] {nx, ny, cur[2], cur[3]+1}); + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + arr = new char[n][m]; + visited = new int[n][m]; + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + visited[i][j] = 2000000; + } + } + } +} From adc50997709075ef4637e12a88cbf2229197f620 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 21 Aug 2022 14:24:02 +0900 Subject: [PATCH 036/163] [BOJ-16985-JAVA] Maaaaaaaaaaze --- java/BOJ/Gold/III/G3_16985.java | 221 ++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_16985.java diff --git a/java/BOJ/Gold/III/G3_16985.java b/java/BOJ/Gold/III/G3_16985.java new file mode 100644 index 0000000..4751962 --- /dev/null +++ b/java/BOJ/Gold/III/G3_16985.java @@ -0,0 +1,221 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16985 + * + * ? 제목: Maaaaaaaaaze + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 평화롭게 문제를 경작하며 생활하는 BOJ 마을 사람들은 더 이상 2차원 미로에 흥미를 느끼지 않는다. 2차원 미로는 너무나 쉽게 탈출이 가능하기 때문이다. 미로를 이 세상 그 누구보다 사랑하는 준현이는 이런 상황을 매우 안타깝게 여겨 아주 큰 상금을 걸고 BOJ 마을 사람들의 관심을 확 끌 수 있는 3차원 미로 탈출 대회를 개최하기로 했다. + * 대회의 규칙은 아래와 같다. + * 5×5 크기의 판이 5개 주어진다. 이중 일부 칸은 참가자가 들어갈 수 있고 일부 칸은 참가자가 들어갈 수 없다. 그림에서 하얀 칸은 참가자가 들어갈 수 있는 칸을, 검은 칸은 참가자가 들어갈 수 없는 칸을 의미한다. + * 참가자는 주어진 판들을 시계 방향, 혹은 반시계 방향으로 자유롭게 회전할 수 있다. 그러나 판을 뒤집을 수는 없다. + * 회전을 완료한 후 참가자는 판 5개를 쌓는다. 판을 쌓는 순서는 참가자가 자유롭게 정할 수 있다. 이렇게 판 5개를 쌓아 만들어진 5×5×5 크기의 큐브가 바로 참가자를 위한 미로이다. 이 때 큐브의 입구는 정육면체에서 참가자가 임의로 선택한 꼭짓점에 위치한 칸이고 출구는 입구와 면을 공유하지 않는 꼭짓점에 위치한 칸이다. + * 참가자는 현재 위치한 칸에서 면으로 인접한 칸이 참가자가 들어갈 수 있는 칸인 경우 그 칸으로 이동할 수 있다. + * 참가자 중에서 본인이 설계한 미로를 가장 적은 이동 횟수로 탈출한 사람이 우승한다. 만약 미로의 입구 혹은 출구가 막혀있거나, 입구에서 출구에 도달할 수 있는 방법이 존재하지 않을 경우에는 탈출이 불가능한 것으로 간주한다. + * 이 대회에서 우승하기 위해서는 미로를 잘 빠져나올 수 있기 위한 담력 증진과 체력 훈련, 그리고 적절한 운이 제일 중요하지만, 가장 적은 이동 횟수로 출구에 도달할 수 있게끔 미로를 만드는 능력 또한 없어서는 안 된다. 주어진 판에서 가장 적은 이동 횟수로 출구에 도달할 수 있게끔 미로를 만들었을 때 몇 번 이동을 해야하는지 구해보자. + * + * ? 입력 & 파싱 + * 첫째 줄부터 25줄에 걸쳐 판이 주어진다. 각 판은 5줄에 걸쳐 주어지며 각 줄에는 5개의 숫자가 빈칸을 사이에 두고 주어진다. 0은 참가자가 들어갈 수 없는 칸, 1은 참가자가 들어갈 수 있는 칸을 의미한다. + * + * 1 1 1 1 1 -> arr[0][0][0] ~ arr[0][0][4] + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 -> arr[0][4][0] ~ arr[0][4][4] + * 1 1 1 1 1 -> arr[1][0][0] ~ arr[1][0][4] + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 -> arr[1][4][0] ~ arr[1][4][4] + * 1 1 1 1 1 -> arr[2][0][0] ~ arr[2][0][4] + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 -> arr[2][4][0] ~ arr[2][4][4] + * 1 1 1 1 1 -> arr[3][0][0] ~ arr[3][0][4] + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 -> arr[3][4][0] ~ arr[3][4][4] + * 1 1 1 1 1 -> arr[4][0][0] ~ arr[4][0][4] + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 -> arr[4][4][0] ~ arr[4][4][4] + * + * ? 출력 + * 첫째 줄에 주어진 판으로 설계된 미로를 탈출하는 가장 적은 이동 횟수를 출력한다. 단, 어떻게 설계하더라도 탈출이 불가능할 경우에는 -1을 출력한다. + * + * 12 + * + * ? 채점 결과 + * * 시간: 1304ms + * * 메모리: 294MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G3_16985 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int[][][] arr = new int[5][5][5]; + + // * 초기 설정 + static int min = Integer.MAX_VALUE; // 최소 이동 거리 + static int[] panel = new int[5]; // 각 층마다 고른 판넬 번호 + static int[][][] maze; // 각 경우의 미로 + static int[][][] visited; // 방문리스트 + + // * 상하좌우 + static int[] dx = {1, -1, 0, 0, 0, 0}; + static int[] dy = {0, 0, 1, -1, 0, 0}; + static int[] dz = {0, 0, 0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력받기 + + // * 2. 각 층마다 판넬을 고르는 모든 경우의 수를 구하고 그때마다 모든 층의 모든 회전의 경우의 수를 골라 BFS + selectPanel(0, 0); + + // * 3. 출력 + bw.write(String.valueOf(min == Integer.MAX_VALUE ? -1 : min)); + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 입력 받기 + public static void input() throws IOException { + for (int k = 0; k < 5; k++) { + for (int i = 0; i < 5; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < 5; j++) { + arr[k][i][j] = Integer.parseInt(st.nextToken()); + } + } + } + } + + // ! 각 층마다 판을 고르는 모든 경우의 수를 구하고 그때마다 getMaze()함수를 실행 + public static void selectPanel(int len, int flag) { + if (len == 5) { + getMaze(); + return; + } + + for (int i = 0; i < 5; i++) { + if ((flag & (1 << (i-1))) != 0) { + continue; + } + + panel[len] = i; + selectPanel(len+1, flag | (1 << (i-1))); + } + } + + // ! 모든 층의 모든 회전의 경우의 수를 구하고 BFS 수행하는 함수 + public static void getMaze() { + maze = new int[5][5][5]; + int[] degree = new int[5]; + + for (int k = 0; k < 1024; k++) { + int p = 0; + int num = k; + while (num != 0) { + degree[p++] = num % 4; + num /= 4; + } + + for (int i = 0; i < 5; i++) { + maze[i] = rotate(degree[i] * 90, panel[i]); + } + + if (maze[0][0][0] == 1) { + visited = new int[5][5][5]; + visited[0][0][0] = 1; + bfs(); + } + } + } + + // ! 2차원 배열을 각도(r)에 따라 회전한 배열을 리턴하는 함수 + // ! r = 0 (0'), 90 (90'), 180 (180'), 270(270') + public static int[][] rotate(int r, int floor) { + if (r == 0) { + return arr[floor]; + } + + int[][] newPanel = new int[5][5]; + + if (r == 90) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + newPanel[j][4-i] = arr[floor][i][j]; + } + } + return newPanel; + } else if (r == 180) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + newPanel[4-i][4-j] = arr[floor][i][j]; + } + } + return newPanel; + } else if (r == 270) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + newPanel[4-j][i] = arr[floor][i][j]; + } + } + return newPanel; + } + + return null; + } + + // ! 일반적인 3차원 배열의 BFS 수행 + public static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {0, 0, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == 4 && cur[1] == 4 && cur[2] == 4) { + if (min > visited[cur[0]][cur[1]][cur[2]]-1) { + min = visited[cur[0]][cur[1]][cur[2]]-1; + } + } + + for (int i = 0; i < 6; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + int nz = cur[2] + dz[i]; + + if (nx < 0 || ny < 0 || nz < 0 || nx >= 5 || ny >= 5 || nz >= 5) { + continue; + } + + if (maze[nx][ny][nz] == 1 && visited[nx][ny][nz] == 0) { + visited[nx][ny][nz] = visited[cur[0]][cur[1]][cur[2]] + 1; + queue.add(new int[] {nx, ny, nz}); + } + } + } + + } +} From 136738308f06e283464855b5240c0e0bf6d64bfa Mon Sep 17 00:00:00 2001 From: dongjji Date: Sun, 21 Aug 2022 16:49:53 +0900 Subject: [PATCH 037/163] =?UTF-8?q?[BOJ-16985-JAVA]=20Maaaaaaaaaze(?= =?UTF-8?q?=EB=93=B1=EA=B8=89=20=EB=B3=80=EA=B2=BD=20G3=20->=20G2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/{III/G3_16985.java => II/G2_16985.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename java/BOJ/Gold/{III/G3_16985.java => II/G2_16985.java} (99%) diff --git a/java/BOJ/Gold/III/G3_16985.java b/java/BOJ/Gold/II/G2_16985.java similarity index 99% rename from java/BOJ/Gold/III/G3_16985.java rename to java/BOJ/Gold/II/G2_16985.java index 4751962..bbd4395 100644 --- a/java/BOJ/Gold/III/G3_16985.java +++ b/java/BOJ/Gold/II/G2_16985.java @@ -56,7 +56,7 @@ * * 언어: JAVA8 * * 시도: 1 */ -package Gold.III; +package Gold.II; import java.io.*; import java.util.Arrays; @@ -64,7 +64,7 @@ import java.util.Queue; import java.util.StringTokenizer; -public class G3_16985 { +public class G2_16985 { static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); static StringTokenizer st; From 4c8c20d4c8a62e2ee1ce8403eaca7cac65879f3a Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Mon, 22 Aug 2022 17:00:56 +0900 Subject: [PATCH 038/163] =?UTF-8?q?[BOJ-5214-JAVA]=20=ED=99=98=EC=8A=B9:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_5214.java | 188 ++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_5214.java diff --git a/java/BOJ/Gold/II/G2_5214.java b/java/BOJ/Gold/II/G2_5214.java new file mode 100644 index 0000000..88cdcc6 --- /dev/null +++ b/java/BOJ/Gold/II/G2_5214.java @@ -0,0 +1,188 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/5214 + * + * ? 제목: 환승 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 아주 먼 미래에 사람들이 가장 많이 사용하는 대중교통은 하이퍼튜브이다. 하이퍼튜브 하나는 역 K개를 서로 연결한다. 1번역에서 N번역으로 가는데 방문하는 최소 역의 수는 몇 개일까? + * + * ? 입력 & 파싱 + * 첫째 줄에 역의 수 N과 한 하이퍼튜브가 서로 연결하는 역의 개수 K, 하이퍼튜브의 개수 M이 주어진다. (1 ≤ N ≤ 100,000, 1 ≤ K, M ≤ 1000) + * 다음 M개 줄에는 하이퍼튜브의 정보가 한 줄에 하나씩 주어진다. 총 K개 숫자가 주어지며, 이 숫자는 그 하이퍼튜브가 서로 연결하는 역의 번호이다. + * + * 9 3 5 -> n, k, m + * 1 2 3 s + * 1 4 5 + * 3 6 7 + * 5 6 7 + * 6 8 9 + * + * ? 출력 + * 첫째 줄에 1번역에서 N번역으로 가는데 방문하는 역의 개수의 최솟값을 출력한다. 만약, 갈 수 없다면 -1을 출력한다. + * + * 4 + * + * ? 채점 결과 + * * 시간: 470ms + * * 메모리: 77MB + * * 언어: JAVA8 + */ +package Gold.II; + +import java.io.*; +import java.util.*; + +public class G2_5214 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + static int n, k, m; + static ArrayList[] station; + static ArrayList[] tube; + + // * 초기 설정 + static int[] stationVisited; + static int[] tubeVisited; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + bfs(); // * 2. 역과 튜브를 모두 정점으로 간주하고 BFS + + // * 3. 정답 출력 + bw.write(String.valueOf(stationVisited[n] == 0 ? -1 : stationVisited[n])); + + br.close(); + bw.flush(); + bw.close(); + } + + // ! BFS + public static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {1, 1}); + stationVisited[1] = 1; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); // cur[0]: number, cur[1] : isStation + + if (cur[1] == 1) { // station + for (int nextTube : station[cur[0]]) { + if (tubeVisited[nextTube] == 0) { + tubeVisited[nextTube] = stationVisited[cur[0]]; + queue.add(new int[] {nextTube, 0}); + } + } + } else { // tube + for (int nextStation : tube[cur[0]]) { + if (stationVisited[nextStation] == 0) { + stationVisited[nextStation] = tubeVisited[cur[0]] + 1; + queue.add(new int[] {nextStation, 1}); + + if (nextStation == n) { + return; + } + } + } + } + } + } + + // ! 입력 받기 + public static void input() throws IOException { + InputReader in = new InputReader(System.in); + + n = in.readInt(); + k = in.readInt(); + m = in.readInt(); + + station = new ArrayList[n+1]; + tube = new ArrayList[m+1]; + stationVisited = new int[n+1]; + tubeVisited= new int[m+1]; + + for (int i = 1; i <= n; i++) { + station[i] = new ArrayList<>(); + } + + for (int i = 1; i <= m; i++) { + tube[i] = new ArrayList<>(); + } + + for (int i = 1; i <= m; i++) { + for (int j = 0; j < k; j++) { + int s = in.readInt(); + tube[i].add(s); + station[s].add(i); + } + } + } + + // ! INPUT 속도 증가 + private static class InputReader { + private InputStream stream; + private byte[] buf = new byte[1024]; + private int curChar; + private int numChars; + private SpaceCharFilter filter; + + public InputReader(InputStream stream) { + this.stream = stream; + } + + public int read() { + if (numChars == -1) { + throw new InputMismatchException(); + } + if (curChar >= numChars) { + curChar = 0; + try { + numChars = stream.read(buf); + } catch (IOException e) { + throw new InputMismatchException(); + } + if (numChars <= 0) { + return -1; + } + } + return buf[curChar++]; + } + + public int readInt() { + int c = read(); + while (isSpaceChar(c)) { + c = read(); + } + int sgn = 1; + if (c == '-') { + sgn = -1; + c = read(); + } + int res = 0; + do { + if (c < '0' || c > '9') { + throw new InputMismatchException(); + } + res *= 10; + res += c - '0'; + c = read(); + } while (!isSpaceChar(c)); + return res * sgn; + } + + public boolean isSpaceChar(int c) { + if (filter != null) { + return filter.isSpaceChar(c); + } + return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; + } + + public interface SpaceCharFilter { + public boolean isSpaceChar(int ch); + } + } +} \ No newline at end of file From 2be4ca3a7faf9b799039f59e68fe1fc54a5d78f1 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 23 Aug 2022 12:28:13 +0900 Subject: [PATCH 039/163] =?UTF-8?q?[BOJ-JAVA-14939]=20=EB=B6=88=20?= =?UTF-8?q?=EB=81=84=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Platinum/V/P5_14939.java | 170 ++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 java/BOJ/Platinum/V/P5_14939.java diff --git a/java/BOJ/Platinum/V/P5_14939.java b/java/BOJ/Platinum/V/P5_14939.java new file mode 100644 index 0000000..32b3138 --- /dev/null +++ b/java/BOJ/Platinum/V/P5_14939.java @@ -0,0 +1,170 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14939 + * + * ? 제목: 불 끄기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 전구 100개가 10×10 정사각형 모양으로 늘어서 있다. 전구에 달린 스위치를 누르면 그 전구와 위, 아래, 왼쪽, 오른쪽에 있는 전구의 상태도 바뀐다. 전구 100개의 상태가 주어지면 모든 전구를 끄기 위해 최소한으로 눌러야 하는 스위치의 개수를 출력하라 + * + * ? 입력 & 파싱 + * 10줄에 10글자씩 입력이 주어진다. #은 꺼진 전구고 O(대문자 알파벳 o)는 켜진 전구다. #과 O외에는 입력으로 주어지지 않는다. + * + * #O######## -> arr[0][0] ~ arr[0][9] + * OOO####### + * #O######## + * ####OO#### + * ###O##O### + * ####OO#### + * ########## + * ########O# + * #######OOO + * ########O# -> arr[9][0] ~ arr[9][9] + * + * ? 출력 + * 모든 전구를 끄기 위해 최소한으로 눌러야 하는 스위치의 개수를 출력하라. 불가능하면 -1를 출력하라. + * + * 4 + * + * ? 채점 결과 + * * 시간: 104ms + * * 메모리: 13MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Platinum.V; + +import java.io.*; + +public class P5_14939 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static boolean[][] arr = new boolean[10][10]; + + // * 초기 설정 + static int count = 0; // 첫번째 줄의 스위치를 켜는 경우의 수마다 모든 불을 껐을 때 스위치를 누른 횟수 + static int min = 101; // 최솟값 + static boolean[] lightCase = new boolean[10]; // 초기 불켜짐 상태 배열 + static boolean[][] light = new boolean[10][10]; // 첫번째 줄의 스위치를 켜는 경우의 수마다 초기 불켜짐 상태 배열을 깊은복사 배열 + + // * 5방(상하좌우 + 현재위치) + static int[] dx = {0, 1, -1, 0, 0}; + static int[] dy = {0, 0, 0, 1, -1}; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + /* + * 2. 첫번째 줄의 스위치를 켜는 방법의 모든 경우의 수를 구하고 + * 모든 불을 끄기 위해 그리디한 방법으로 + * 현재 스위치를 기준으로 위의 불이 켜져있을때 해당 스위치를 눌러서 + * 현재 줄의 바로 윗줄을 확실하게 끄는 방법을 선택 + * 10번째 줄의 스위치까지 그리디한 방법으로 누르고 나면 마지막 줄의 불의 상태를 보고 모두 꺼져있을 때 + * count와 최솟값을 비교하여 업데이트 + */ + findCase(0); + + // * 3. 출력 + System.out.println(min == 101 ? -1 : min); + } + + // ! 입력 받기 + public static void input() throws IOException { + for (int i = 0; i < 10; i++) { + int p = 0; + for (char c : br.readLine().toCharArray()) { + arr[i][p++] = c == 'O'; + } + } + } + + // ! 2차원 배열 깊은 복사: light <- arr + public static void copy() { + for (int i = 0; i < 10; i++) { + light[i] = arr[i].clone(); + } + } + + // ! 첫번째 줄의 스위치를 누르는 모든 경우의 수 구하기 2^10 = 1024 + public static void findCase(int len) { + if (len == 10) { + turnOff(); + return; + } + + lightCase[len] = true; + findCase(len+1); + + lightCase[len] = false; + findCase(len+1); + } + + // ! 모든 불을 끄기 위한 그리디한 방법 중 실제로 모든 불이 꺼졌을 때 count값과 최솟값을 비교하여 업데이트하는 함수 + public static void turnOff() { + count = 0; // 스위치 작동 횟수 초기화 + copy(); // 초기 불켜짐 상태를 깊은복사해서 새롭게 초기화 + + // * 첫번째 줄 스위치 작동 (lightCase) + for (int i = 0; i < 10; i++) { + if (lightCase[i]) { + count++; + for (int j = 0; j < 5; j++) { + int ny = dy[j]; + int nx = i + dx[j]; + + if (ny < 0 || nx < 0 || ny >= 10 || nx >= 10) { + continue; + } + + if (light[ny][nx]) { + light[ny][nx] = false; + } else { + light[ny][nx] = true; + } + } + } + } + + // * 첫번째 줄 스위치 작동 후의 결과를 가지고 스위치 작동 + for (int i = 1; i < 10; i++) { + for (int j = 0; j < 10; j++) { + if (light[i-1][j]) { + count++; + for (int k = 0; k < 5; k++) { + int ny = i + dy[k]; + int nx = j + dx[k]; + + if (ny < 0 || nx < 0 || ny >= 10 || nx >= 10) { + continue; + } + + if (light[ny][nx]) { + light[ny][nx] = false; + } else { + light[ny][nx] = true; + } + } + } + } + } + + // * 마지막 줄이 모두 꺼져있을 때 최솟값 업데이트 + if (lastCheck() && count < min) { + min = count; + } + } + + // ! 마지막 줄의 불이 모두 꺼졌는지 체크하는 함수 + public static boolean lastCheck() { + for (int i = 0; i < 10; i++) { + if (light[9][i]) { + return false; + } + } + return true; + } +} From ca377ed2fce8415fdd47e5cc46a3a8a6c844da9b Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 24 Aug 2022 14:40:33 +0900 Subject: [PATCH 040/163] =?UTF-8?q?[BOJ-11967-JAVA]=20=EB=B6=88=EC=BC=9C?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_11967.java | 165 +++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_11967.java diff --git a/java/BOJ/Gold/II/G2_11967.java b/java/BOJ/Gold/II/G2_11967.java new file mode 100644 index 0000000..40e8eac --- /dev/null +++ b/java/BOJ/Gold/II/G2_11967.java @@ -0,0 +1,165 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11967 + * + * ? 제목: 불켜기 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 농부 존은 최근에 N × N개의 방이 있는 거대한 헛간을 새로 지었다. 각 방은 (1, 1)부터 (N,N)까지 번호가 매겨져있다(2 ≤ N ≤ 100). 어둠을 무서워하는 암소 베시는 최대한 많은 방에 불을 밝히고 싶어한다. + * 베시는 유일하게 불이 켜져있는 방인 (1, 1)방에서 출발한다. 어떤 방에는 다른 방의 불을 끄고 켤 수 있는 스위치가 달려있다. 예를 들어, (1, 1)방에 있는 스위치로 (1, 2)방의 불을 끄고 켤 수 있다. 베시는 불이 켜져있는 방으로만 들어갈 수 있고, 각 방에서는 상하좌우에 인접한 방으로 움직일 수 있다. + * 베시가 불을 켤 수 있는 방의 최대 개수를 구하시오. + * + * ? 입력 & 파싱 + * 첫 번째 줄에는 N(2 ≤ N ≤ 100)과, M(1 ≤ M ≤ 20,000)이 정수로 주어진다. + * 다음 M줄에는 네 개의 정수 x, y, a, b가 주어진다. (x, y)방에서 (a, b)방의 불을 켜고 끌 수 있다는 의미이다. 한 방에 여러개의 스위치가 있을 수 있고, 하나의 불을 조절하는 스위치 역시 여러개 있을 수 있다. + * + * 3 6 -> n m + * 1 1 1 2 -> x y a b + * 2 1 2 2 -> x y a b + * 1 1 1 3 -> x y a b + * 2 3 3 1 -> x y a b + * 1 3 1 2 -> x y a b + * 1 3 2 1 -> x y a b + * + * ? 출력 + * 베시가 불을 켤 수 있는 방의 최대 개수를 출력하시오. + * + * 5 + * + * ? 채점 결과 + * * 시간: 240ms + * * 메모리: 23MB + * * 언어: JAVA8 + * * 시도: 5 + */ +package Gold.II; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G2_11967 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static ArrayList[][] light; + + // * 초기 설정 + static boolean[][] visited; + static boolean[][] lightOn; + + // * 상하좌우 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + bfs(); // * 2. BFS + + System.out.println(count()); // * 3. 불켜진 개수 + } + + // ! BFS + public static void bfs() { + visited[1][1] = true; // 초기위치 방문표시 + lightOn[1][1] = true; // 초기위치 불켜짐 표시 + + Queue queue = new LinkedList<>(); + queue.add(new int[] {1, 1}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + // * 현재 위치에서 불을 켤 수 있는 곳이 불이 꺼져있다면 켜주기 + for (int[] l : light[cur[0]][cur[1]]) { + if (!lightOn[l[0]][l[1]]) { + lightOn[l[0]][l[1]] = true; + } + } + + // * 불을 새로 킨 곳 중에서(visited[l[0]][l[1]] = false) 바로 인접한 곳 하나라도 방문한 적이 있다면 + // * 해당 위치를 방문표시 후 큐에 삽입 + for (int[] l: light[cur[0]][cur[1]]) { + for (int i = 0; i < 4; i++) { + int nx = l[0] + dx[i]; + int ny = l[1] + dy[i]; + + if (nx < 1 || ny < 1 || nx > n || ny > n) { + continue; + } + + if (!visited[l[0]][l[1]]) { + if (visited[nx][ny]) { + visited[l[0]][l[1]] = true; + queue.add(new int[] {l[0], l[1]}); + break; + } + } + } + } + + // * 인접한 곳이 불이 켜져있고 방문하지 않으면 방문표시 후 큐에 삽입 + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 1 || ny < 1 || nx > n || ny > n) { + continue; + } + + if (!visited[nx][ny] && lightOn[nx][ny]) { + visited[nx][ny] = true; + queue.add(new int[] {nx, ny}); + } + } + } + } + + // ! 모든 방의 불의 켜진 개수를 세는 함수 + public static int count() { + int c = 0; + for (int i = 1; i < n+1; i++) { + for (int j =1 ; j < n+1; j++) { + if (lightOn[i][j]) { + c++; + } + } + } + return c; + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + light = new ArrayList[n+1][n+1]; + visited = new boolean[n+1][n+1]; + lightOn = new boolean[n+1][n+1]; + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + light[i][j] = new ArrayList<>(); + } + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int x = Integer.parseInt(st.nextToken()); + int y = Integer.parseInt(st.nextToken()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + light[x][y].add(new int[] {a, b}); + } + + } +} \ No newline at end of file From 5d1b852c4d958e2c03d57d91a929a877802fca00 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 25 Aug 2022 13:04:19 +0900 Subject: [PATCH 041/163] =?UTF-8?q?[BOJ-2447-JAVA]=20=EB=B3=84=20=EC=B0=8D?= =?UTF-8?q?=EA=B8=B0=20-=2010?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2447.java | 123 +++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2447.java diff --git a/java/BOJ/Gold/V/G5_2447.java b/java/BOJ/Gold/V/G5_2447.java new file mode 100644 index 0000000..b0eaee8 --- /dev/null +++ b/java/BOJ/Gold/V/G5_2447.java @@ -0,0 +1,123 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2447 + * + * ? 제목: 별 찍기 - 10 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 재귀적인 패턴으로 별을 찍어 보자. N이 3의 거듭제곱(3, 9, 27, ...)이라고 할 때, 크기 N의 패턴은 N×N 정사각형 모양이다. + * 크기 3의 패턴은 가운데에 공백이 있고, 가운데를 제외한 모든 칸에 별이 하나씩 있는 패턴이다. + * + * *** + * * * + * *** + * + * N이 3보다 클 경우, 크기 N의 패턴은 공백으로 채워진 가운데의 (N/3)×(N/3) 정사각형을 크기 N/3의 패턴으로 둘러싼 형태이다. 예를 들어 크기 27의 패턴은 예제 출력 1과 같다. + * + * ? 입력 & 파싱 + * 첫째 줄에 N이 주어진다. N은 3의 거듭제곱이다. 즉 어떤 정수 k에 대해 N=3k이며, 이때 1 ≤ k < 8이다. + * + * 27 + * + * ? 출력 + * 첫째 줄부터 N번째 줄까지 별을 출력한다. + * + * *************************** + * * ** ** ** ** ** ** ** ** * + * *************************** + * *** ****** ****** *** + * * * * ** * * ** * * * + * *** ****** ****** *** + * *************************** + * * ** ** ** ** ** ** ** ** * + * *************************** + * ********* ********* + * * ** ** * * ** ** * + * ********* ********* + * *** *** *** *** + * * * * * * * * * + * *** *** *** *** + * ********* ********* + * * ** ** * * ** ** * + * ********* ********* + * *************************** + * * ** ** ** ** ** ** ** ** * + * *************************** + * *** ****** ****** *** + * * * * ** * * ** * * * + * *** ****** ****** *** + * *************************** + * * ** ** ** ** ** ** ** ** * + * *************************** + * + * ? 채점 결과 + * * 시간: 196ms + * * 메모리: 22MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.V; + +import java.io.*; + +public class G5_2447 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + static int n; + + // * 초기 설정 + static char[][] arr; + + public static void main(String[] args) throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new char[n][n]; + + find(0, 0, n, false); + + for (int i = 0; i < n; i++) { + bw.write(arr[i]); + bw.write("\n"); + } + + br.close(); + bw.flush(); + bw.close(); + } + + public static void find(int x, int y, int n, boolean isBlank) { + // 빈공간일 때 + if (isBlank) { + for (int i = x; i < x + n; i++) { + for (int j = y; j < y + n; j++) { + arr[i][j] = ' '; + } + } + return; + } + + // 더이상 쪼갤 수 없을 때 + if (n == 1) { + arr[x][y] = '*'; + return; + } + + + // 9블럭으로 나누었을 때 한변의 길이 + int side = n / 3; + int cnt = 0; + for (int i = x; i < x + n; i += side) { + for (int j = y; j < y + n; j += side) { + cnt++; + if (cnt == 5) { + find(i, j, side, true); + } else { + find(i, j, side, false); + } + } + } + } +} From 8cb318a4aa6fe3bb88b33a1c4a6d95fee4fd5a36 Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 26 Aug 2022 12:29:38 +0900 Subject: [PATCH 042/163] =?UTF-8?q?[BOJ-1992-JAVA]=20=EC=BF=BC=EB=93=9C?= =?UTF-8?q?=ED=8A=B8=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_1992.java | 101 +++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_1992.java diff --git a/java/BOJ/Silver/I/S1_1992.java b/java/BOJ/Silver/I/S1_1992.java new file mode 100644 index 0000000..6e2a1f8 --- /dev/null +++ b/java/BOJ/Silver/I/S1_1992.java @@ -0,0 +1,101 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1992 + * + * ? 제목: 쿼드트리 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 흑백 영상을 압축하여 표현하는 데이터 구조로 쿼드 트리(Quad Tree)라는 방법이 있다. 흰 점을 나타내는 0과 검은 점을 나타내는 1로만 이루어진 영상(2차원 배열)에서 같은 숫자의 점들이 한 곳에 많이 몰려있으면, 쿼드 트리에서는 이를 압축하여 간단히 표현할 수 있다. + * 주어진 영상이 모두 0으로만 되어 있으면 압축 결과는 "0"이 되고, 모두 1로만 되어 있으면 압축 결과는 "1"이 된다. 만약 0과 1이 섞여 있으면 전체를 한 번에 나타내지를 못하고, 왼쪽 위, 오른쪽 위, 왼쪽 아래, 오른쪽 아래, 이렇게 4개의 영상으로 나누어 압축하게 되며, 이 4개의 영역을 압축한 결과를 차례대로 괄호 안에 묶어서 표현한다 + * 위 그림에서 왼쪽의 영상은 오른쪽의 배열과 같이 숫자로 주어지며, 이 영상을 쿼드 트리 구조를 이용하여 압축하면 "(0(0011)(0(0111)01)1)"로 표현된다. N ×N 크기의 영상이 주어질 때, 이 영상을 압축한 결과를 출력하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에는 영상의 크기를 나타내는 숫자 N 이 주어진다. N 은 언제나 2의 제곱수로 주어지며, 1 ≤ N ≤ 64의 범위를 가진다. 두 번째 줄부터는 길이 N의 문자열이 N개 들어온다. 각 문자열은 0 또는 1의 숫자로 이루어져 있으며, 영상의 각 점들을 나타낸다. + * + * 8 -> n + * 11110000 -> arr[0][0] ~ arr[0][n-1] + * 11110000 + * 00011100 + * 00011100 + * 11110000 + * 11110000 + * 11110011 + * 11110011 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 영상을 압축한 결과를 출력한다. + * + * ((110(0101))(0010)1(0001)) + * + * ? 채점 결과 + * * 시간: 84ms + * * 메모리: 13MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.*; + +public class S1_1992 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + static int n; + static char[][] arr; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + bw.write(zip(0, 0, n)); // * 2. 분할 정복 + + br.close(); + bw.flush(); + bw.close(); + } + + // ! 분할 정복 + public static String zip(int x, int y, int n) { + if (n == 1) { + return String.valueOf(arr[x][y]); + } + + boolean isSame = true; + for (int i = x; i < x + n; i++) { + for (int j = y; j < y + n;j ++) { + if (arr[x][y] != arr[i][j]) { + isSame = false; + break; + } + } + } + + if (isSame) { + return String.valueOf(arr[x][y]); + } + + int side = n / 2; + StringBuilder sb = new StringBuilder(); + sb.append("(" + + zip(x, y, side) + + zip(x, y+side, side) + + zip(x+side, y, side) + + zip(x+side, y+side, side) + + ")"); + + return sb.toString(); + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new char[n][n]; + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } + +} From b77f05fdd299b645410a46ebf23b9db023afbac7 Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 26 Aug 2022 18:31:35 +0900 Subject: [PATCH 043/163] =?UTF-8?q?[BOJ-17135-JAVA]=20=EC=BA=90=EC=8A=AC?= =?UTF-8?q?=20=EB=94=94=ED=8E=9C=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_17135.java | 182 ++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_17135.java diff --git a/java/BOJ/Gold/III/G3_17135.java b/java/BOJ/Gold/III/G3_17135.java new file mode 100644 index 0000000..1146dbc --- /dev/null +++ b/java/BOJ/Gold/III/G3_17135.java @@ -0,0 +1,182 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17135 + * + * ? 제목: 캐슬 디펜스 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 캐슬 디펜스는 성을 향해 몰려오는 적을 잡는 턴 방식의 게임이다. 게임이 진행되는 곳은 크기가 N×M인 격자판으로 나타낼 수 있다. 격자판은 1×1 크기의 칸으로 나누어져 있고, 각 칸에 포함된 적의 수는 최대 하나이다. 격자판의 N번행의 바로 아래(N+1번 행)의 모든 칸에는 성이 있다. + * 성을 적에게서 지키기 위해 궁수 3명을 배치하려고 한다. 궁수는 성이 있는 칸에 배치할 수 있고, 하나의 칸에는 최대 1명의 궁수만 있을 수 있다. 각각의 턴마다 궁수는 적 하나를 공격할 수 있고, 모든 궁수는 동시에 공격한다. 궁수가 공격하는 적은 거리가 D이하인 적 중에서 가장 가까운 적이고, 그러한 적이 여럿일 경우에는 가장 왼쪽에 있는 적을 공격한다. 같은 적이 여러 궁수에게 공격당할 수 있다. 공격받은 적은 게임에서 제외된다. 궁수의 공격이 끝나면, 적이 이동한다. 적은 아래로 한 칸 이동하며, 성이 있는 칸으로 이동한 경우에는 게임에서 제외된다. 모든 적이 격자판에서 제외되면 게임이 끝난다. + * 게임 설명에서 보다시피 궁수를 배치한 이후의 게임 진행은 정해져있다. 따라서, 이 게임은 궁수의 위치가 중요하다. 격자판의 상태가 주어졌을 때, 궁수의 공격으로 제거할 수 있는 적의 최대 수를 계산해보자. + * 격자판의 두 위치 (r1, c1), (r2, c2)의 거리는 |r1-r2| + |c1-c2|이다. + * + * ? 입력 & 파싱 + * 첫째 줄에 격자판 행의 수 N, 열의 수 M, 궁수의 공격 거리 제한 D가 주어진다. 둘째 줄부터 N개의 줄에는 격자판의 상태가 주어진다. 0은 빈 칸, 1은 적이 있는 칸이다. + * + * 5 5 1 -> n m d + * 0 0 0 0 0 -> arr[0][0] ~ arr[0][m-1] + * 0 0 0 0 0 + * 0 0 0 0 0 + * 0 0 0 0 0 + * 1 1 1 1 1 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 첫째 줄에 궁수의 공격으로 제거할 수 있는 적의 최대 수를 출력한다. + * + * 3 + * + * ? 제한 + * 3 ≤ N, M ≤ 15 + * 1 ≤ D ≤ 10 + * + * ? 채점 결과 + * * 시간: 172ms + * * 메모리: 40MB + * * 언어: JAVA8 + * * 시도: 7 + */ +package Gold.III; + +import java.io.*; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G3_17135 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m, d; + static int[][] arr; + + // * 초기 설정 + static int max = 0; // 죽일 수 있는 적의 최댓값 + static int count = 0; // 궁수 배치마다 죽일 수 있는 적의 수 + static int[] archers = new int[3]; // 궁수 배치 + static int[][] castle; // 궁수 배치마다 초기 적의 위치 + + // * 3방( 왼쪽 위 오른쪽 ) + static int[] dx = {0, -1, 0}; + static int[] dy = {-1, 0, 1}; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + setArcher(0, 0); // * 2. 궁수 배치의 모든 조합마다 죽일 수 있는 적의 수를 구하고 그때의 최댓값 구하기 + + bw.write(String.valueOf(max)); // * 3. 정답 출력 + + // 닫기 + br.close(); + bw.flush(); + bw.close(); + } + + // ! 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + d = Integer.parseInt(st.nextToken()); + + arr = new int[n][m]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + + } + + // ! 궁수 배치의 모든 경우의 수 구하기(조합) + public static void setArcher(int len, int start) { + if (len == 3) { + play(); // * 각 배치마다 play 실행 + return; + } + + for (int i = start; i < m; i++) { + archers[len] = i; + setArcher(len+1, i+1); + } + } + + // ! 궁수 배치가 끝났다면 n번의 턴동안 궁수들이 죽일 수 있는 적들을 누적해서 더하기(count) + public static void play() { + count = 0; + castle = new int[n][m]; + for (int i = 0; i < n; i++) { + castle[i] = arr[i].clone(); + } + + for (int k = 0; k < n; k++) { + for (int i = 0; i < archers.length; i++) { + findEnemy(archers[i]); // * 현재 격자 상태에서 3명의 궁수들이 적을 죽이기(한명의 적이 여러명의 궁수에게 맞을 수 있음) + } + down(); // * 한 턴이 끝났다면 밑으로 한칸 내림 + } + + // * 모든 턴이 끝났다면 죽인 적의 수를 최댓값과 비교하여 업데이트 + if (max < count) { + max = count; + } + } + + // ! 현재 궁수의 위치에서 죽일 수 있는 적을 찾기 + public static void findEnemy(int archer) { + boolean[][] visited = new boolean[n][m]; + Queue queue = new LinkedList<>(); + queue.add(new int[] {n, archer, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[2] == d) { + continue; + } + + for (int i = 0; i < 3; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m || visited[nx][ny]) { + continue; + } + + // 적의 위치일 때 + if (castle[nx][ny] >= 1) { + if (castle[nx][ny] == 1) { + count++; + } + castle[nx][ny]++; // * 중복으로 적을 공격할 수 있기 때문에 중복 공격당했다는 것을 표시하기 위해 +1 + return; + } + + visited[nx][ny] = true; + queue.add(new int[] {nx, ny, cur[2]+1}); + } + } + + } + + // ! 적들의 위치를 한칸 내리는 함수 + public static void down() { + int[][] newArr = new int[n][m]; + for (int i = 1; i < n; i++) { + for (int j = 0; j < m; j++) { + if (castle[i-1][j] >= 2) { // * 적이 죽었다면 0으로 셋팅 + newArr[i][j] = 0; + } else { + newArr[i][j] = castle[i-1][j]; + } + } + } + castle = newArr; + } +} From 00a0040707494490f6ebbfaceb13c21a15023d30 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 27 Aug 2022 14:53:25 +0900 Subject: [PATCH 044/163] =?UTF-8?q?[BOJ-14867-JAVA]=20=EB=AC=BC=ED=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_14867.java | 182 +++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_14867.java diff --git a/java/BOJ/Gold/II/G2_14867.java b/java/BOJ/Gold/II/G2_14867.java new file mode 100644 index 0000000..8c0c624 --- /dev/null +++ b/java/BOJ/Gold/II/G2_14867.java @@ -0,0 +1,182 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14867 + * + * ? 제목: 물통 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 용량이 다른 두 개의 빈 물통 A, B가 있다. 이 물통들에 물을 채우고 비우는 일을 반복하여 두 물통을 원하는 상태(목표하는 양의 물을 담은 상태)가 되도록 만들고자 한다. 물통 이외에는 물의 양을 정확히 잴 수 있는 방법이 없으며, 가능한 작업은 다음과 같은 세 종류가 전부이다. + * [F(x): Fill x]: 물통 x에 물을 가득 채운다. (물을 채우기 전에 물통 x가 비어있는지 여부는 관계없음. 다른 물통은 그대로 둠) + * [E(x): Empty x]: 물통 x의 물을 모두 버린다. (다른 물통은 그대로 둠) + * [M(x,y): Move water from x to y)]: 물통 x의 물을 물통 y에 붓는다. 이때 만약 물통 x에 남아 있는 물의 양이 물통 y에 남아 있는 빈 공간보다 적거나 같다면 물통 x의 물을 물통 y에 모두 붓는다. 만약 물통 x에 남아 있는 물의 양이 물통 y에 남아 있는 빈 공간보다 많다면 부을 수 있는 만큼 최대로 부어 물통 y를 꽉 채우고 나머지는 물통 x에 남긴다. + * 예를 들어, 물통 A와 B의 용량이 각각 2리터와 5리터라고 하자. 두 물통 모두 빈 상태에서 시작하여 최종적으로 물통 A에는 2리터, 물통 B에는 4리터 물을 남기길 원할 경우, 다음과 같은 순서로 작업을 수행하면 총 8회의 작업으로 원하는 상태에 도달할 수 있다. + * (0,0)→[F(B)]→(0,5)→[M(B,A)]→(2,3)→[E(A)]→(0,3)→[M(B,A)]→(2,1)→[E(A)]→(0,1)→[M(B,A)]→(1,0)→[F(B)]→(1,5)→[M(B,A)]→(2,4) + * 하지만, 작업 순서를 아래와 같이 한다면 필요한 작업 총 수가 5회가 된다. + * (0,0)→[F(A)]→(2,0)→[M(A,B)]→(0,2)→[F(A)]→(2,2)→[M(A,B)]→(0,4)→[F(A)]→(2,4) + * 두 물통의 용량과 원하는 최종 상태를 입력으로 받은 후, 두 물통이 비어 있는 상태에서 시작하여 최종 상태에 도달하기 위한 최소 작업 수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 표준 입력으로 물통 A의 용량을 나타내는 정수 a(1 ≤ a < 100,000), 물통 B의 용량을 나타내는 정수 b(a < b ≤ 100,000), 최종 상태에서 물통 A에 남겨야 하는 물의 용량을 나타내는 정수 c(0 ≤ c ≤ a), 최종 상태에서 물통 B에 남겨야 하는 물의 용량을 나타내는 정수 d(0 ≤ d ≤ b)가 공백으로 분리되어 한 줄에 주어진다. + * + * 3 7 3 2 -> aMax bMax aEnd bEnd + * + * ? 출력 + * 목표 상태에 도달하는 최소 작업 수를 나타내는 정수를 표준 출력으로 출력한다. 만약 목표 상태에 도달하는 방법이 없다면 –1을 출력한다. + * + * 9 + * + * ? 서브태스크 + * 번호 배점 제한 + * 1 9 A 물통의 용량은 1리터 + * 2 14 B 물통의 용량은 A 물통의 용량의 배수 + * 3 34 1 ≤ a, b ≤ 1,000 + * 4 43 원래의 제약조건 이외에 아무 제약조건이 없다. + * + * ? 채점 결과 + * * 시간: 1140ms + * * 메모리: 234MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.II; + +import java.io.*; +import java.util.*; + +public class G2_14867 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int aMax; + static int bMax; + static int aEnd; + static int bEnd; + + // * 초기 설정 + static HashSet visited = new HashSet<>(); // 방문 해쉬셋 + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + st = new StringTokenizer(br.readLine()); + aMax = Integer.parseInt(st.nextToken()); + bMax = Integer.parseInt(st.nextToken()); + aEnd = Integer.parseInt(st.nextToken()); + bEnd = Integer.parseInt(st.nextToken()); + + // * 2. BFS 수행 + int answer = bfs(); + + // * 3. 정답 출력 + System.out.println(answer); + } + + /* + 1. A 비우기 + 2. B 비우기 + 3. A 가득채우기 + 4. B 가득채우기 + 5. A -> B + 6. B -> A + */ + + // ! BFS + public static int bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {0, 0, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + // 정답 + if (cur[0] == aEnd && cur[1] == bEnd) { + return cur[2]; + } + + // 1 + if (cur[0] != 0) { + if (!isVisited(0, cur[1])) { + queue.add(new int[] {0, cur[1], cur[2]+1}); + } + } + + // 2 + if (cur[1] != 0) { + if (!isVisited(cur[0], 0)) { + queue.add(new int[] {cur[0], 0, cur[2]+1}); + } + } + + // 3 + if (cur[0] != aMax) { + if (!isVisited(aMax, cur[1])) { + queue.add(new int[] {aMax, cur[1], cur[2]+1}); + } + } + + // 4 + if (cur[1] != bMax) { + if (!isVisited(cur[0], bMax)) { + queue.add(new int[] {cur[0], bMax, cur[2]+1}); + } + + } + + // 5 + if (cur[0] != 0) { + int[] next = moveAtoB(cur[0], cur[1], cur[2]); + if (!isVisited(next[0], next[1])) { + queue.add(next); + } + } + + // 6 + if (cur[1] != 0) { + int[] next = moveBtoA(cur[0], cur[1], cur[2]); + if (!isVisited(next[0], next[1])) { + queue.add(next); + } + } + } + + return -1; + } + + // ! HashSet을 이용하여 이미 방문했는지 확인하고 방문하지 않았다면 방문표시하고 true를 리턴하는 함수 + public static boolean isVisited(int a, int b) { + String v = a + "," + b; + if (visited.contains(v)) { + return true; + } + visited.add(v); + return false; + } + + // ! A에 있는 물을 B로 옮기는 함수 + public static int[] moveAtoB(int a, int b, int c) { + if (a + b > bMax) { + a -= (bMax - b); + b = bMax; + } else { + b += a; + a = 0; + } + + return new int[] {a, b, c+1}; + } + + // ! B에 있는 물을 A로 옮기는 함수 + public static int[] moveBtoA(int a, int b, int c) { + if (a + b > aMax) { + b -= (aMax - a); + a = aMax; + } else { + a += b; + b = 0; + } + + return new int[] {a, b, c+1}; + } +} From ec86ec765f0fe59afa5bae055cd087b9703847e2 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 28 Aug 2022 14:00:31 +0900 Subject: [PATCH 045/163] =?UTF-8?q?[BOJ-2151-JAVA]=20=EA=B1=B0=EC=9A=B8=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_2151.java | 158 +++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_2151.java diff --git a/java/BOJ/Gold/III/G3_2151.java b/java/BOJ/Gold/III/G3_2151.java new file mode 100644 index 0000000..c4ca15a --- /dev/null +++ b/java/BOJ/Gold/III/G3_2151.java @@ -0,0 +1,158 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2151 + * + * ? 제목: 거울 설치 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 채영이는 거울을 들여다보는 것을 참 좋아한다. 그래서 집 곳곳에 거울을 설치해두고 집 안을 돌아다닐 때마다 거울을 보곤 한다. + * 채영이는 새 해를 맞이하여 이사를 하게 되었는데, 거울을 좋아하는 그녀의 성격 때문에 새 집에도 거울을 매달만한 위치가 여러 곳 있다. 또한 채영이네 새 집에는 문이 두 개 있는데, 채영이는 거울을 잘 설치하여 장난을 치고 싶어졌다. 즉, 한 쪽 문에서 다른 쪽 문을 볼 수 있도록 거울을 설치하고 싶어졌다. + * 채영이네 집에 대한 정보가 주어졌을 때, 한 쪽 문에서 다른 쪽 문을 볼 수 있도록 하기 위해 설치해야 하는 거울의 최소 개수를 구하는 프로그램을 작성하시오. + * 거울을 설치할 때에는 45도 기울어진 대각선 방향으로 설치해야 한다. 또한 모든 거울은 양면 거울이기 때문에 양 쪽 모두에서 반사가 일어날 수 있다. 채영이는 거울을 매우 많이 가지고 있어서 거울이 부족한 경우는 없다고 하자. + * 거울을 어떻게 설치해도 한 쪽 문에서 다른 쪽 문을 볼 수 없는 경우는 주어지지 않는다. + * + * ? 입력 + * 첫째 줄에 집의 크기 N (2 ≤ N ≤ 50)이 주어진다. 다음 N개의 줄에는 N개의 문자로 집에 대한 정보가 주어진다. ‘#’는 문이 설치된 곳으로 항상 두 곳이며, ‘.’은 아무 것도 없는 것으로 빛은 이 곳을 통과한다. ‘!’은 거울을 설치할 수 있는 위치를 나타내고, ‘*’은 빛이 통과할 수 없는 벽을 나타낸다. + * + * 5 -> n + * ***#* -> arr[0][0] ~ arr[0][n-1] + * *.!.* + * *!.!* + * *.!.* + * *#*** -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 첫째 줄에 설치해야 할 거울의 최소 개수를 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 228ms + * * 메모리: 18MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.PriorityQueue; + +public class G3_2151 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static int n; + static char[][] arr; + + // * 초기 설정 + static int answer = 0; // 정답 + static int[][][] visited; // 방문리스트 + static int[][] door = new int[2][2]; // 문위치 + + // * 상하좌우 (0: 수평이동, 1: 수직이동) + static int[][] dx = {{-1, 1}, {0, 0}}; + static int[][] dy = {{0, 0}, {-1, 1}}; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + findDoor(); // * 2. 문 위치 찾기 + findMirror(); // * 3. 다익스트라 + System.out.println(answer); // * 4. 출력 + } + + // ! 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new char[n][n]; + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + + visited = new int[n][n][2]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + for (int k = 0; k < 2; k++) { + visited[i][j][k] = 10000; + } + } + } + } + + // ! 문 위치 찾기 + public static void findDoor() { + byte p = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (arr[i][j] == '#') { + door[p][0] = i; + door[p][1] = j; + p++; + } + } + } + } + + // 0: 수평, 1 : 수직 + // ! 다익스트라 알고리즘 + public static void findMirror() { + // * 우선순위 큐 사용 + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[3] - b[3]); + pq.add(new int[] {door[0][0], door[0][1], 0, 0}); // 초기위치 수평이동 + pq.add(new int[] {door[0][0], door[0][1], 1, 0}); // 초기위치 수직이동 + visited[door[0][0]][door[0][1]][0] = 0; + visited[door[0][0]][door[0][1]][1] = 0; + + // * 다익스트라 + while (!pq.isEmpty()) { + int[] cur = pq.poll(); + + // 반대쪽 문에 도착했을 때 종료 + if (cur[0] == door[1][0] && cur[1] == door[1][1]) { + answer = cur[3]; + return; + } + + // 이미 해당 위치 와 이동 방향에 더 적은 거울설치 개수로 도착한 경우 패스 + if (visited[cur[0]][cur[1]][cur[2]] < cur[3]) { + continue; + } + + // 거울을 놓을 수 있을 때 + if (arr[cur[0]][cur[1]] == '!') { + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + int nx = cur[0] + dx[i][j]; + int ny = cur[1] + dy[i][j]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= n || arr[nx][ny] == '*') { + continue; + } + + if (visited[nx][ny][i] > (i == cur[2] ? cur[3] : cur[3]+1)) { + visited[nx][ny][i] = (i == cur[2] ? cur[3] : cur[3]+1); + pq.add(new int[] {nx, ny, i, i == cur[2] ? cur[3] : cur[3]+1}); + } + } + } + } else { // 거울을 놓을 수 없을 때 + for (int i = 0; i < 2; i++) { + int nx = cur[0] + dx[cur[2]][i]; + int ny = cur[1] + dy[cur[2]][i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= n || arr[nx][ny] == '*') { + continue; + } + + if (visited[nx][ny][cur[2]] > cur[3]) { + visited[nx][ny][cur[2]] = cur[3]; + pq.add(new int[] {nx, ny, cur[2], cur[3]}); + } + } + } + } + } +} \ No newline at end of file From f8421f12381b186865e64b47762f103c25791176 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 29 Aug 2022 13:01:53 +0900 Subject: [PATCH 046/163] =?UTF-8?q?[BOJ-17071-JAVA]=20=EC=88=A8=EB=B0=94?= =?UTF-8?q?=EA=BC=AD=EC=A7=88=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Platinum/V/P5_17071.java | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 java/BOJ/Platinum/V/P5_17071.java diff --git a/java/BOJ/Platinum/V/P5_17071.java b/java/BOJ/Platinum/V/P5_17071.java new file mode 100644 index 0000000..97f9ba8 --- /dev/null +++ b/java/BOJ/Platinum/V/P5_17071.java @@ -0,0 +1,133 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17071 + * + * ? 제목: 숨바꼭질 5 + * ? 시간 제한: 0.25초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 500,000)에 있고, 동생은 점 K(0 ≤ K ≤ 500,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다. 동생은 항상 걷기만 한다. 동생은 항상 매 초마다 이동을 하며, 이동은 가속이 붙는다. 동생이 이동하는 거리는 이전에 이동한 거리보다 1을 더한 만큼 이동한다. 즉, 동생의 처음 위치는 K, 1초가 지난 후 위치는 K+1, 2초가 지난 후 위치는 K+1+2, 3초가 지난 후의 위치는 K+1+2+3이다. + * 수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오. 동생을 찾는 위치는 정수 좌표이어야 하고, 수빈이가 0보다 작은 좌표로, 50만보다 큰 좌표로 이동하는 것은 불가능하다. + * + * ? 입력 & 파싱 + * 첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다. + * + * 5 17 -> n m (편의상 k가 아니라 m으로) + * + * ? 출력 + * 수빈이가 동생을 찾는 가장 빠른 시간을 출력한다. 수빈이가 동생을 찾을 수 없거나, 찾는 위치가 500,000을 넘는 경우에는 -1을 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 280ms + * * 메모리: 74MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Platinum.V; + +import java.io.*; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class P5_17071 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + + // * 초기 설정 + static int[][] dp; + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + // * 2. DP 방문리스트 초기화 + dp = new int[500001][2]; + for (int i = 0; i < dp.length; i++) { + for (int j = 0; j < 2; j++) { + dp[i][j] = -1; + } + } + + // * 3. BFS 수행 + bfs(); + + // * 4. 수빈이가 동생을 찾는 가장 빠른 시간 출력 + System.out.println(nextLocation()); + } + + // ! BFS 수행해서 n(수빈)이 해당 위치까지 갈 수 있는 짝수횟수의 최솟값, 홀수횟수의 최솟값을 따로 구함 + // * 이동 시간이 짝수일 때는 dp[현재위치][0] = 이동 시간 + // * 이동 시간이 홀수일 때는 dp[현재위치][1] = 이동 시간 + public static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {n, 0}); + dp[n][0] = 0; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + for (int i = -1; i <= 1; i++) { + // 다음 위치 + int next; + if (i == 0) { + next = cur[0] * 2; + } else { + next = cur[0] + i; + } + + // 범위 체크 + if (next < 0 || next > 500000) { + continue; + } + + int k = cur[1] % 2 == 0 ? 0 : 1; // 홀 or 짝 + + if (dp[next][k] == -1) { + dp[next][k] = cur[1]+1; + queue.add(new int[] {next, cur[1]+1}); + } + } + } + } + + // ! 현재 위치에서 수빈이가 해당 위치를 최소로 방문한 홀수시간과 짝수시간을 비교하여 가장 빨리 잡는 시간을 찾는 함수 + // * 10의 위치를 수빈이가 홀수로는 3회, 짝수로는 4회 방문했다고 하고 동생은 그 위치를 시간이 5일때 방문했다면 + // * 홀수 방문했을 때 3회 -> 옆으로 갔다가 다시 들어오는 횟수(+2)가 가능하므로 5회가 최소 + public static int nextLocation() { + if (n == m) { + return 0; + } + + int cur = m; + int time = 0; + int min = Integer.MAX_VALUE; + + while (true) { + time++; + cur += time; + + if (cur > 500000) { + break; + } + + if (time >= dp[cur][0] && (time % 2 == dp[cur][0] % 2)) { + min = Math.min(min, time); + } + + if (time >= dp[cur][1] && (time % 2 == dp[cur][1] % 2)) { + min = Math.min(min, time); + } + } + + return min == Integer.MAX_VALUE ? -1 : min; + } +} From cd3620a642784da828ef207a44b7bbdbfdd028c4 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 30 Aug 2022 15:00:00 +0900 Subject: [PATCH 047/163] [BOJ-9251-JAVA] LCS --- java/BOJ/Gold/V/G5_9251.java | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_9251.java diff --git a/java/BOJ/Gold/V/G5_9251.java b/java/BOJ/Gold/V/G5_9251.java new file mode 100644 index 0000000..c8fb82c --- /dev/null +++ b/java/BOJ/Gold/V/G5_9251.java @@ -0,0 +1,71 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/9251 + * + * ? 제목: LCS + * ? 시간 제한: 0.1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. + * 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다. + * + * ? 입력 & 파싱 + * 첫째 줄과 둘째 줄에 두 문자열이 주어진다. 문자열은 알파벳 대문자로만 이루어져 있으며, 최대 1000글자로 이루어져 있다. + * + * ACAYKP -> word1 + * CAPCAK -> word2 + * + * ? 출력 + * 첫째 줄에 입력으로 주어진 두 문자열의 LCS의 길이를 출력한다. + * + * 4 + * + * ? 채점 결과 + * * 시간: 104ms + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class G5_9251 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static char[] word1, word2; + + // * 초기 설정 + static int[][] lcs; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. Bottom-Up 방식 LCS + for (int i = 1; i <= word1.length; i++) { + for (int j = 1; j <= word2.length; j++) { + if (word1[i - 1] == word2[j - 1]) { + lcs[i][j] = lcs[i - 1][j - 1] + 1; + } else { + lcs[i][j] = Math.max(lcs[i-1][j], lcs[i][j-1]); + } + } + } + + System.out.println(lcs[word1.length][word2.length]); + } + + // ! 입력 받기 + public static void input() throws IOException { + word1 = br.readLine().toCharArray(); + word2 = br.readLine().toCharArray(); + + lcs = new int[word1.length+1][word2.length+1]; + + } +} From 53fcb59bc9457d1d8168d9d3b48801c1e986d5a2 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 31 Aug 2022 10:16:20 +0900 Subject: [PATCH 048/163] =?UTF-8?q?[BOJ-2579-JAVA]=20=EA=B3=84=EB=8B=A8=20?= =?UTF-8?q?=EC=98=A4=EB=A5=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/III/S3_2579.java | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 java/BOJ/Silver/III/S3_2579.java diff --git a/java/BOJ/Silver/III/S3_2579.java b/java/BOJ/Silver/III/S3_2579.java new file mode 100644 index 0000000..2c3f059 --- /dev/null +++ b/java/BOJ/Silver/III/S3_2579.java @@ -0,0 +1,81 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2579 + * + * ? 제목: 계단 오르기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다. + * 연속된 세 개의 계단을 모두 밟아서는 안 된다. 단, 시작점은 계단에 포함되지 않는다. + * 마지막 도착 계단은 반드시 밟아야 한다. + * 따라서 첫 번째 계단을 밟고 이어 두 번째 계단이나, 세 번째 계단으로 오를 수 있다. 하지만, 첫 번째 계단을 밟고 이어 네 번째 계단으로 올라가거나, 첫 번째, 두 번째, 세 번째 계단을 연속해서 모두 밟을 수는 없다. + * 각 계단에 쓰여 있는 점수가 주어질 때 이 게임에서 얻을 수 있는 총 점수의 최댓값을 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 입력의 첫째 줄에 계단의 개수가 주어진다. + * 둘째 줄부터 한 줄에 하나씩 제일 아래에 놓인 계단부터 순서대로 각 계단에 쓰여 있는 점수가 주어진다. 계단의 개수는 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10,000이하의 자연수이다. + * + * 6 -> n + * 10 -> stair[1] + * 20 + * 15 + * 25 + * 10 + * 20 -> stair[n] + * + * ? 출력 + * 첫째 줄에 계단 오르기 게임에서 얻을 수 있는 총 점수의 최댓값을 출력한다. + * + * 75 + * + * ? 채점 결과 + * * 시간: 76ms + * * 메모리: 115MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Silver.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S3_2579 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + static int n; + static int[] stair; + static int[] dp; + + public static void main(String[] args) throws IOException { + input(); + + if (n == 1) { + System.out.println(stair[n]); + return; + } + + dp[1] = stair[1]; + dp[2] = stair[1] + stair[2]; + + for (int i = 3; i <= n; i++) { + dp[i] = Math.max(dp[i-3] + stair[i-1], dp[i-2]) + stair[i]; + } + + System.out.println(dp[n]); + + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + stair = new int[n + 1]; + dp = new int[n + 1]; + + for (int i = 1 ; i <= n; i++) { + stair[i] = Integer.parseInt(br.readLine()); + } + } +} From 340c1f1d5c53c63146fa944461a5e6d7ffdda457 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 31 Aug 2022 10:52:53 +0900 Subject: [PATCH 049/163] =?UTF-8?q?[BOJ-1932-JAVA]=20=EC=A0=95=EC=88=98=20?= =?UTF-8?q?=EC=82=BC=EA=B0=81=ED=98=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_1932.java | 91 ++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_1932.java diff --git a/java/BOJ/Silver/I/S1_1932.java b/java/BOJ/Silver/I/S1_1932.java new file mode 100644 index 0000000..307f6a1 --- /dev/null +++ b/java/BOJ/Silver/I/S1_1932.java @@ -0,0 +1,91 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1932 + * + * ? 제목: 정수 삼각형 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 7 + * 3 8 + * 8 1 0 + * 2 7 4 4 + * 4 5 2 6 5 + * 위 그림은 크기가 5인 정수 삼각형의 한 모습이다. + * + * 맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다. + * 삼각형의 크기는 1 이상 500 이하이다. 삼각형을 이루고 있는 각 수는 모두 정수이며, 범위는 0 이상 9999 이하이다. + * + * ? 입력 & 파싱 + * 첫째 줄에 삼각형의 크기 n(1 ≤ n ≤ 500)이 주어지고, 둘째 줄부터 n+1번째 줄까지 정수 삼각형이 주어진다. + * + * 5 -> n + * 7 -> arr[0][0] + * 3 8 -> arr[1][0] ~ arr[1][1] + * 8 1 0 -> arr[2][0] ~ arr[2][2] + * 2 7 4 4 -> arr[3][0] ~ arr[3][3] + * 4 5 2 6 5 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 첫째 줄에 합이 최대가 되는 경로에 있는 수의 합을 출력한다. + * + * 30 + * + * ? 채점 결과 + * * 시간: 412ms + * * 메모리: 28MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class S1_1932 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + + // * 초기 설정 + static int[][] arr; + + // # 메인 함수 + public static void main(String[] args) throws IOException { + input(); // 1. 입력 받기 + + // 2. Top-Down 방식 DP (Tabulation) + for (int i = 1; i < n; i++) { + for (int j = 0; j < i+1; j++) { + if (j == 0) { + arr[i][j] = arr[i-1][j] + arr[i][j]; + } else { + arr[i][j] = Math.max(arr[i-1][j-1], arr[i-1][j]) + arr[i][j]; + } + } + } + + // 3. 정답 출력 + int max = Arrays.stream(arr[n-1]).max().getAsInt(); + System.out.println(max); + } + + // # 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n][n]; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < i+1; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 33cdd10fadd44ff0f315a5ca109dc6061bc2c287 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 1 Sep 2022 09:15:19 +0900 Subject: [PATCH 050/163] =?UTF-8?q?[BOJ-1912-JAVA]=20=EC=97=B0=EC=86=8D?= =?UTF-8?q?=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/II/S2_1912.java | 78 +++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 java/BOJ/Silver/II/S2_1912.java diff --git a/java/BOJ/Silver/II/S2_1912.java b/java/BOJ/Silver/II/S2_1912.java new file mode 100644 index 0000000..89ec257 --- /dev/null +++ b/java/BOJ/Silver/II/S2_1912.java @@ -0,0 +1,78 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1912 + * + * ? 제목: 연속합 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * n개의 정수로 이루어진 임의의 수열이 주어진다. 우리는 이 중 연속된 몇 개의 수를 선택해서 구할 수 있는 합 중 가장 큰 합을 구하려고 한다. 단, 수는 한 개 이상 선택해야 한다. + * 예를 들어서 10, -4, 3, 1, 5, 6, -35, 12, 21, -1 이라는 수열이 주어졌다고 하자. 여기서 정답은 12+21인 33이 정답이 된다. + * + * ? 입력 & 파싱 + * 첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다. + * + * 10 -> n + * 10 -4 3 1 5 6 -35 12 21 -1 -> arr[0] ~ arr[n-1] + * + * ? 출력 + * 첫째 줄에 답을 출력한다. + * + * 33 + * + * ? 채점 결과 + * * 시간: 220ms + * * 메모리: 22MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.II; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class S2_1912 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int max; // 연속합 최댓값 + static int[] dp; // 연속합 최댓값 DP + + // # 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + max = arr[0]; // 최댓값 초기화 + dp[0] = arr[0]; // 시작값 초기화 + + // * 2. DP(Tabulation) + for (int i = 1; i < n; i++) { + dp[i] = Math.max(arr[i] + dp[i-1], arr[i]); + max = Math.max(max, dp[i]); + } + + // * 3. 정답 출력 + System.out.println(max); + } + + // # 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n]; + dp = new int[n]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + } +} From 7a7c58e356d024421017805df7b8c6ae98c6a69c Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 1 Sep 2022 10:07:34 +0900 Subject: [PATCH 051/163] =?UTF-8?q?[BOJ-2156-JAVA]=20=ED=8F=AC=EB=8F=84?= =?UTF-8?q?=EC=A3=BC=20=EC=8B=9C=EC=8B=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_2156.java | 88 ++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_2156.java diff --git a/java/BOJ/Silver/I/S1_2156.java b/java/BOJ/Silver/I/S1_2156.java new file mode 100644 index 0000000..360ecfb --- /dev/null +++ b/java/BOJ/Silver/I/S1_2156.java @@ -0,0 +1,88 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2156 + * + * ? 제목: 포도주 시식 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 효주는 포도주 시식회에 갔다. 그 곳에 갔더니, 테이블 위에 다양한 포도주가 들어있는 포도주 잔이 일렬로 놓여 있었다. 효주는 포도주 시식을 하려고 하는데, 여기에는 다음과 같은 두 가지 규칙이 있다. + * 포도주 잔을 선택하면 그 잔에 들어있는 포도주는 모두 마셔야 하고, 마신 후에는 원래 위치에 다시 놓아야 한다. + * 연속으로 놓여 있는 3잔을 모두 마실 수는 없다. + * 효주는 될 수 있는 대로 많은 양의 포도주를 맛보기 위해서 어떤 포도주 잔을 선택해야 할지 고민하고 있다. 1부터 n까지의 번호가 붙어 있는 n개의 포도주 잔이 순서대로 테이블 위에 놓여 있고, 각 포도주 잔에 들어있는 포도주의 양이 주어졌을 때, 효주를 도와 가장 많은 양의 포도주를 마실 수 있도록 하는 프로그램을 작성하시오. + * 예를 들어 6개의 포도주 잔이 있고, 각각의 잔에 순서대로 6, 10, 13, 9, 8, 1 만큼의 포도주가 들어 있을 때, 첫 번째, 두 번째, 네 번째, 다섯 번째 포도주 잔을 선택하면 총 포도주 양이 33으로 최대로 마실 수 있다. + * + * ? 입력 & 파싱 + * 첫째 줄에 포도주 잔의 개수 n이 주어진다. (1 ≤ n ≤ 10,000) 둘째 줄부터 n+1번째 줄까지 포도주 잔에 들어있는 포도주의 양이 순서대로 주어진다. 포도주의 양은 1,000 이하의 음이 아닌 정수이다. + * + * 6 -> n + * 6 -> arr[1] + * 10 + * 13 + * 9 + * 8 + * 1 -> arr[n] + * + * ? 출력 + * 첫째 줄에 최대로 마실 수 있는 포도주의 양을 출력한다. + * + * 33 + * + * ? 채점 결과 + * * 시간: 96ms + * * 메모리: 13MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S1_2156 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int[] dp; + + // # 메인 함수 + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // 길이가 1인 경우(예외 케이스) + if (n == 1) { + System.out.println(arr[1]); + return; + } + + // * 2. DP(Tabulation) + dp[1] = arr[1]; + dp[2] = arr[1] + arr[2]; + for (int i = 3; i <= n; i++) { + dp[i] = Math.max(dp[i - 1], + Math.max(dp[i - 2] + arr[i], + dp[i - 3] + arr[i - 1] + arr[i])); + } + + // * 3. 정답 출력 + System.out.println(dp[n]); + } + + // # 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n+1]; + dp = new int[n+1]; + + for (int i = 1; i <= n; i++) { + arr[i] = Integer.parseInt(br.readLine()); + } + } +} From fbf5bc171197bb26ec5e6ec171daa09fd99a5088 Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 2 Sep 2022 11:11:17 +0900 Subject: [PATCH 052/163] =?UTF-8?q?[BOJ-10844-JAVA]=20=EC=89=AC=EC=9A=B4?= =?UTF-8?q?=20=EA=B3=84=EB=8B=A8=20=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_10844.java | 74 +++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_10844.java diff --git a/java/BOJ/Silver/I/S1_10844.java b/java/BOJ/Silver/I/S1_10844.java new file mode 100644 index 0000000..51f6cc4 --- /dev/null +++ b/java/BOJ/Silver/I/S1_10844.java @@ -0,0 +1,74 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/10844 + * + * ? 제목: 쉬운 계단 수 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 45656이란 수를 보자. + * 이 수는 인접한 모든 자리의 차이가 1이다. 이런 수를 계단 수라고 한다. + * N이 주어질 때, 길이가 N인 계단 수가 총 몇 개 있는지 구해보자. 0으로 시작하는 수는 계단수가 아니다. + * + * ? 입력 & 파싱 + * 첫째 줄에 N이 주어진다. N은 1보다 크거나 같고, 100보다 작거나 같은 자연수이다. + * + * 1 -> n + * + * ? 출력 + * 첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다. + * + * 9 + * + * ? 채점 결과 + * * 시간: 76ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S1_10844 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + int n = Integer.parseInt(br.readLine()); + + // * 초기 설정 + int answer = 0; + int div = 1_000_000_000; + int[][] dp = new int[10][n+1]; + + // * 2. DP(Tabulation) + for (int i = 1; i <= 9; i++) { + dp[i][1] = 1; + } + + for (int i = 1; i < n; i++) { + for (int j = 0; j < 10; j++) { + if (j-1 >= 0) { + dp[j-1][i+1] = (dp[j-1][i+1] % div + dp[j][i] % div) % div; + } + + if (j+1 < 10) { + dp[j+1][i+1] = (dp[j+1][i+1] % div + dp[j][i] % div) % div; + } + } + } + + // * 3. 1의자리수 0부터 9까지 나올 수 있는 모든 경우의 수 합(+나머지연산) + for (int i = 0; i < 10; i++) { + answer = (answer % div + dp[i][n] % div) % div; + } + + // * 4. 정답 출력 + System.out.println(answer); + } +} From 20c723be45d5e3cbe76a468826d75d79b4560f4d Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 2 Sep 2022 11:28:17 +0900 Subject: [PATCH 053/163] =?UTF-8?q?[BOJ-11727-JAVA]=202xn=20=ED=83=80?= =?UTF-8?q?=EC=9D=BC=EB=A7=81=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/III/S3_11727.java | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 java/BOJ/Silver/III/S3_11727.java diff --git a/java/BOJ/Silver/III/S3_11727.java b/java/BOJ/Silver/III/S3_11727.java new file mode 100644 index 0000000..b6f8493 --- /dev/null +++ b/java/BOJ/Silver/III/S3_11727.java @@ -0,0 +1,69 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11727 + * + * ? 제목: 2xn 타일링 2 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 2×n 직사각형을 1×2, 2×1과 2×2 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 n이 주어진다. (1 ≤ n ≤ 1,000) + * + * 12 -> n + * + * ? 출력 + * 첫째 줄에 2×n 크기의 직사각형을 채우는 방법의 수를 10,007로 나눈 나머지를 출력한다. + * + * 2731 + * + * ? 채점 결과 + * * 시간: 76ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S3_11727 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static int n; + + // * 초기 설정 + static int div = 10_007; + static int[] dp; + + // ! 메인 함수 + public static void main(String[] args) throws IOException { + // * 1 입력 받기 + n = Integer.parseInt(br.readLine()); + dp = new int[n+1]; + + // * 2. DP(tabulation) + 3. 출력 + System.out.println(tile()); + } + + // ! DP(tabulation) + public static int tile() { + if (n == 1) { + return 1; + } + + dp[1] = 1; + dp[2] = 3; + + for (int i = 3; i <= n; i++) { + dp[i] = ((dp[i-2] % div + dp[i-2] % div) % div + dp[i-1] % div) % div; + } + + return dp[n]; + } +} From 9737d40cf57745492d72c270fa5fa1dda0e26119 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 3 Sep 2022 12:51:29 +0900 Subject: [PATCH 054/163] =?UTF-8?q?[BOJ-1010-JAVA]=20=EB=8B=A4=EB=A6=AC=20?= =?UTF-8?q?=EB=86=93=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/V/S5_1010.java | 99 ++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 java/BOJ/Silver/V/S5_1010.java diff --git a/java/BOJ/Silver/V/S5_1010.java b/java/BOJ/Silver/V/S5_1010.java new file mode 100644 index 0000000..ff976c7 --- /dev/null +++ b/java/BOJ/Silver/V/S5_1010.java @@ -0,0 +1,99 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1010 + * + * ? 제목: 다리 놓기 + * ? 시간 제한: 0.5초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 재원이는 한 도시의 시장이 되었다. 이 도시에는 도시를 동쪽과 서쪽으로 나누는 큰 일직선 모양의 강이 흐르고 있다. 하지만 재원이는 다리가 없어서 시민들이 강을 건너는데 큰 불편을 겪고 있음을 알고 다리를 짓기로 결심하였다. 강 주변에서 다리를 짓기에 적합한 곳을 사이트라고 한다. 재원이는 강 주변을 면밀히 조사해 본 결과 강의 서쪽에는 N개의 사이트가 있고 동쪽에는 M개의 사이트가 있다는 것을 알았다. (N ≤ M) + * 재원이는 서쪽의 사이트와 동쪽의 사이트를 다리로 연결하려고 한다. (이때 한 사이트에는 최대 한 개의 다리만 연결될 수 있다.) 재원이는 다리를 최대한 많이 지으려고 하기 때문에 서쪽의 사이트 개수만큼 (N개) 다리를 지으려고 한다. 다리끼리는 서로 겹쳐질 수 없다고 할 때 다리를 지을 수 있는 경우의 수를 구하는 프로그램을 작성하라. + * + * ? 입력 & 파싱 + * 입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트케이스에 대해 강의 서쪽과 동쪽에 있는 사이트의 개수 정수 N, M (0 < N ≤ M < 30)이 주어진다. + * + * 3 + * 2 2 + * 1 5 + * 13 29 + * + * ? 출력 + * 각 테스트 케이스에 대해 주어진 조건하에 다리를 지을 수 있는 경우의 수를 출력한다. + * + * 1 + * 5 + * 67863915 + * + * ? 채점 결과 + * * 시간: 80ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.V; + +import java.io.*; +import java.util.StringTokenizer; + +public class S5_1010 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int t, n, m; + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + t = Integer.parseInt(br.readLine()); + + // * 2. DP(Tabulation: Bottom-Up) + int[][] dp = new int[31][31]; + + // * START-CASE + for (int i = 1; i <= 30; i++) { + dp[1][i] = i; + } + + for (int i = 2; i <= 30; i++) { + for (int j = 1; j <= 30; j++) { + if (i > j) { + continue; + } + + if (i == j) { + dp[i][j] = 1; + } else { + dp[i][j] = dp[i-1][j-1] + dp[i][j-1]; + } + } + } + + // * 3. 각 케이스마다 정답 출력 + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < t; i++) { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + sb.append(dp[n][m] + "\n"); + } + + System.out.println(sb.toString()); + } +} + +/* + 규칙: dp[i][j] = dp[i-1][j-1] + dp[i][j-1]; + 1 2 3 4 5 6 7 8 9 10 + 1 1 2 3 4 5 6 7 8 9 10 + 2 1 3 6 10 15 21 28 36 45 + 3 1 + 4 1 + 5 1 + 6 1 + 7 1 + + + */ From ee26f1960bbc6e1e55812dc68b7866f903f483f0 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 3 Sep 2022 12:51:53 +0900 Subject: [PATCH 055/163] =?UTF-8?q?[BOJ-2193-JAVA]=20=EC=9D=B4=EC=B9=9C?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/III/S3_2193.java | 78 ++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 java/BOJ/Silver/III/S3_2193.java diff --git a/java/BOJ/Silver/III/S3_2193.java b/java/BOJ/Silver/III/S3_2193.java new file mode 100644 index 0000000..32b7043 --- /dev/null +++ b/java/BOJ/Silver/III/S3_2193.java @@ -0,0 +1,78 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2193 + * + * ? 제목: 이친수 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 0과 1로만 이루어진 수를 이진수라 한다. 이러한 이진수 중 특별한 성질을 갖는 것들이 있는데, 이들을 이친수(pinary number)라 한다. 이친수는 다음의 성질을 만족한다. + * 이친수는 0으로 시작하지 않는다. + * 이친수에서는 1이 두 번 연속으로 나타나지 않는다. 즉, 11을 부분 문자열로 갖지 않는다. + * 예를 들면 1, 10, 100, 101, 1000, 1001 등이 이친수가 된다. 하지만 0010101이나 101101은 각각 1, 2번 규칙에 위배되므로 이친수가 아니다. + * N(1 ≤ N ≤ 90)이 주어졌을 때, N자리 이친수의 개수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 N이 주어진다. + * + * 3 -> n + * + * ? 출력 + * 첫째 줄에 N자리 이친수의 개수를 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 76ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Silver.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S3_2193 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static int n; + + // * 초기 설정 + static long[] dp; + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + n = Integer.parseInt(br.readLine()); + + // * 예외 처리 + if (n == 1) { + System.out.println(1); + return; + } + + // * 2. end case + dp = new long[n+1]; + dp[1] = 1; + dp[2] = 1; + + // * 3. DP(Memoization) + topDown(n); + + // * 4. 출력 + System.out.println(dp[n]); + } + + // # DP(Top-Down: Memoization) + public static long topDown(int idx) { + if (dp[idx] > 0) { + return dp[idx]; + } + + dp[idx] = topDown(idx-1) + topDown(idx-2); + return dp[idx]; + } +} From c1d8d787d99d8434655bc39b6a15d470eb4e8560 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 4 Sep 2022 14:09:23 +0900 Subject: [PATCH 056/163] =?UTF-8?q?[BOJ-JAVA-14501]=20=ED=87=B4=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/III/S3_14501.java | 116 ++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 java/BOJ/Silver/III/S3_14501.java diff --git a/java/BOJ/Silver/III/S3_14501.java b/java/BOJ/Silver/III/S3_14501.java new file mode 100644 index 0000000..c9fce80 --- /dev/null +++ b/java/BOJ/Silver/III/S3_14501.java @@ -0,0 +1,116 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14501 + * + * ? 제목: 퇴사 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 상담원으로 일하고 있는 백준이는 퇴사를 하려고 한다. + * 오늘부터 N+1일째 되는 날 퇴사를 하기 위해서, 남은 N일 동안 최대한 많은 상담을 하려고 한다. + * 백준이는 비서에게 최대한 많은 상담을 잡으라고 부탁을 했고, 비서는 하루에 하나씩 서로 다른 사람의 상담을 잡아놓았다. + * 각각의 상담은 상담을 완료하는데 걸리는 기간 Ti와 상담을 했을 때 받을 수 있는 금액 Pi로 이루어져 있다. + * + * N = 7인 경우에 다음과 같은 상담 일정표를 보자. + * + * 1일 2일 3일 4일 5일 6일 7일 + * Ti 3 5 1 1 2 4 2 + * Pi 10 20 10 20 15 40 200 + * 1일에 잡혀있는 상담은 총 3일이 걸리며, 상담했을 때 받을 수 있는 금액은 10이다. 5일에 잡혀있는 상담은 총 2일이 걸리며, 받을 수 있는 금액은 15이다. + * 상담을 하는데 필요한 기간은 1일보다 클 수 있기 때문에, 모든 상담을 할 수는 없다. 예를 들어서 1일에 상담을 하게 되면, 2일, 3일에 있는 상담은 할 수 없게 된다. 2일에 있는 상담을 하게 되면, 3, 4, 5, 6일에 잡혀있는 상담은 할 수 없다. + * 또한, N+1일째에는 회사에 없기 때문에, 6, 7일에 있는 상담을 할 수 없다. + * 퇴사 전에 할 수 있는 상담의 최대 이익은 1일, 4일, 5일에 있는 상담을 하는 것이며, 이때의 이익은 10+20+15=45이다. + * 상담을 적절히 했을 때, 백준이가 얻을 수 있는 최대 수익을 구하는 프로그램을 작성하시오. + * + * ? 입력 + * 첫째 줄에 N (1 ≤ N ≤ 15)이 주어진다. + * 둘째 줄부터 N개의 줄에 Ti와 Pi가 공백으로 구분되어서 주어지며, 1일부터 N일까지 순서대로 주어진다. (1 ≤ Ti ≤ 5, 1 ≤ Pi ≤ 1,000) + * + * 7 -> n + * 3 10 -> time[1], price[1] + * 5 20 + * 1 10 + * 1 20 + * 2 15 + * 4 40 + * 2 200 -> time[n], price[n] + * + * ? 출력 + * 첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다. + * + * 45 + * + * ? 채점 결과 + * * 시간: 76ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Silver.III; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class S3_14501 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + + // * 초기 설정 + static int[] time; + static int[] price; + static int[] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation) + for (int i = 1; i <= n+1; i++) { + for (int j = 1; j < i; j++) { + if (j + time[j] <= i) { + dp[i] = Math.max(dp[i], dp[j] + price[j]); + } + } + } + + System.out.println(dp[n+1]); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + time = new int[n+2]; + price = new int[n+2]; + dp = new int[n+2]; + + for (int i = 1; i <= n; i++) { + st = new StringTokenizer(br.readLine()); + time[i] = Integer.parseInt(st.nextToken()); + price[i] = Integer.parseInt(st.nextToken()); + } + } +} + +/* +DP Table + +7 +3 10 +5 20 +1 10 +1 20 +2 15 +4 40 +2 200 + +0 3 5 1 1 2 4 2 +0 10 20 10 20 15 40 200 + +0 1 2 3 4 5 6 7 +0 0 0 10 30 30 45 45 + */ From 40c61e99735b73dc4f410bcec813c00ce6ba44ba Mon Sep 17 00:00:00 2001 From: dongjji Date: Sun, 4 Sep 2022 16:22:11 +0900 Subject: [PATCH 057/163] =?UTF-8?q?[BOJ-1904-JAVA]=2001=ED=83=80=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/III/S3_1904.java | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 java/BOJ/Silver/III/S3_1904.java diff --git a/java/BOJ/Silver/III/S3_1904.java b/java/BOJ/Silver/III/S3_1904.java new file mode 100644 index 0000000..fe610aa --- /dev/null +++ b/java/BOJ/Silver/III/S3_1904.java @@ -0,0 +1,79 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1904 + * + * ? 제목: 01타일 + * ? 시간 제한: 0.75초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 지원이에게 2진 수열을 가르쳐 주기 위해, 지원이 아버지는 그에게 타일들을 선물해주셨다. 그리고 이 각각의 타일들은 0 또는 1이 쓰여 있는 낱장의 타일들이다. + * 어느 날 짓궂은 동주가 지원이의 공부를 방해하기 위해 0이 쓰여진 낱장의 타일들을 붙여서 한 쌍으로 이루어진 00 타일들을 만들었다. 결국 현재 1 하나만으로 이루어진 타일 또는 0타일을 두 개 붙인 한 쌍의 00타일들만이 남게 되었다. + * 그러므로 지원이는 타일로 더 이상 크기가 N인 모든 2진 수열을 만들 수 없게 되었다. 예를 들어, N=1일 때 1만 만들 수 있고, N=2일 때는 00, 11을 만들 수 있다. (01, 10은 만들 수 없게 되었다.) 또한 N=4일 때는 0011, 0000, 1001, 1100, 1111 등 총 5개의 2진 수열을 만들 수 있다. + * 우리의 목표는 N이 주어졌을 때 지원이가 만들 수 있는 모든 가짓수를 세는 것이다. 단 타일들은 무한히 많은 것으로 가정하자. + * + * ? 입력 & 파싱 + * 첫 번째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 1,000,000) + * + * 4 -> n + * + * ? 출력 + * 첫 번째 줄에 지원이가 만들 수 있는 길이가 N인 모든 2진 수열의 개수를 15746으로 나눈 나머지를 출력한다. + * + * 5 + * + * ? 채점 결과 + * * 시간: 104ms + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Silver.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S3_1904 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 초기 설정 + static int div = 15746; + static int[] dp; + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + int n = Integer.parseInt(br.readLine()); + + // * 2. 예외 케이스 처리 + if (n <= 3) { + System.out.println(n); + return; + } + + // * DP Table 초기화 + dp = new int[n+1]; + dp[1] = 1; + dp[2] = 2; + dp[3] = 3; + /* + dp[i-1] + 0011 + 1001 + 1111 + + dp[i-2] + 0000 + 1100 + */ + + // * 3. DP(Tabulation: Bottom-Up) + for (int i = 4; i <= n; i++) { + dp[i] = (dp[i-1] % div + dp[i-2] % div) % div; + } + + // * 4. 출력 + System.out.println(dp[n]); + } + +} From 2fca8bea4c92e4d0e6d1eb40f8adb0668f5b7ce5 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 5 Sep 2022 10:04:57 +0900 Subject: [PATCH 058/163] =?UTF-8?q?[BOJ-JAVA-11052]=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=20=EA=B5=AC=EB=A7=A4=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_11052.java | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_11052.java diff --git a/java/BOJ/Silver/I/S1_11052.java b/java/BOJ/Silver/I/S1_11052.java new file mode 100644 index 0000000..3740367 --- /dev/null +++ b/java/BOJ/Silver/I/S1_11052.java @@ -0,0 +1,88 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11052 + * + * ? 제목: 카드 구매하기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 요즘 민규네 동네에서는 스타트링크에서 만든 PS카드를 모으는 것이 유행이다. + * PS카드는 PS(Problem Solving)분야에서 유명한 사람들의 아이디와 얼굴이 적혀있는 카드이다. 각각의 카드에는 등급을 나타내는 색이 칠해져 있고, 다음과 같이 8가지가 있다. + * + * 전설카드 + * 레드카드 + * 오렌지카드 + * 퍼플카드 + * 블루카드 + * 청록카드 + * 그린카드 + * 그레이카드 + * + * 카드는 카드팩의 형태로만 구매할 수 있고, 카드팩의 종류는 카드 1개가 포함된 카드팩, 카드 2개가 포함된 카드팩, ... 카드 N개가 포함된 카드팩과 같이 총 N가지가 존재한다. + * 민규는 카드의 개수가 적은 팩이더라도 가격이 비싸면 높은 등급의 카드가 많이 들어있을 것이라는 미신을 믿고 있다. 따라서, 민규는 돈을 최대한 많이 지불해서 카드 N개 구매하려고 한다. 카드가 i개 포함된 카드팩의 가격은 Pi원이다. + * 예를 들어, 카드팩이 총 4가지 종류가 있고, P1 = 1, P2 = 5, P3 = 6, P4 = 7인 경우에 민규가 카드 4개를 갖기 위해 지불해야 하는 금액의 최댓값은 10원이다. 2개 들어있는 카드팩을 2번 사면 된다. + * P1 = 5, P2 = 2, P3 = 8, P4 = 10인 경우에는 카드가 1개 들어있는 카드팩을 4번 사면 20원이고, 이 경우가 민규가 지불해야 하는 금액의 최댓값이다. + * 마지막으로, P1 = 3, P2 = 5, P3 = 15, P4 = 16인 경우에는 3개 들어있는 카드팩과 1개 들어있는 카드팩을 구매해 18원을 지불하는 것이 최댓값이다. + * 카드 팩의 가격이 주어졌을 때, N개의 카드를 구매하기 위해 민규가 지불해야 하는 금액의 최댓값을 구하는 프로그램을 작성하시오. N개보다 많은 개수의 카드를 산 다음, 나머지 카드를 버려서 N개를 만드는 것은 불가능하다. 즉, 구매한 카드팩에 포함되어 있는 카드 개수의 합은 N과 같아야 한다. + * + * ? 입력 & 파싱 + * 첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다. (1 ≤ N ≤ 1,000) + * 둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 ≤ Pi ≤ 10,000) + * + * 4 + * 1 5 6 7 + * + * ? 출력 + * 첫째 줄에 민규가 카드 N개를 갖기 위해 지불해야 하는 금액의 최댓값을 출력한다. + * + * 10 + * + * ? 채점 결과 + * * 시간: 100ms + * * 메모리: 12MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class S1_11052 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] price; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + int[] dp = price.clone(); // * 2. DP Table 초기화 + + // * 3. DP(Tabulation: Bottom-Up) + for (int i = 1; i <= n; i++) { + for (int j = i; j <= n; j++) { + dp[j] = Math.max(dp[j], dp[j-i] + price[i]); + } + } + + // * 4. 정답 출력 + System.out.println(dp[n]); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + price = new int[n+1]; + st = new StringTokenizer(br.readLine()); + for (int i = 1; i <= n; i++) { + price[i] = Integer.parseInt(st.nextToken()); + } + } +} From 8125a9ed8aec735b17933403443d81b8067edbd3 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 5 Sep 2022 10:35:31 +0900 Subject: [PATCH 059/163] =?UTF-8?q?[BOJ-JAVA-9465]=20=EC=8A=A4=ED=8B=B0?= =?UTF-8?q?=EC=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_9465.java | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_9465.java diff --git a/java/BOJ/Silver/I/S1_9465.java b/java/BOJ/Silver/I/S1_9465.java new file mode 100644 index 0000000..418b2c9 --- /dev/null +++ b/java/BOJ/Silver/I/S1_9465.java @@ -0,0 +1,106 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/9465 + * + * ? 제목: 스티커 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 상근이의 여동생 상냥이는 문방구에서 스티커 2n개를 구매했다. 스티커는 그림 (a)와 같이 2행 n열로 배치되어 있다. 상냥이는 스티커를 이용해 책상을 꾸미려고 한다. + * 상냥이가 구매한 스티커의 품질은 매우 좋지 않다. 스티커 한 장을 떼면, 그 스티커와 변을 공유하는 스티커는 모두 찢어져서 사용할 수 없게 된다. 즉, 뗀 스티커의 왼쪽, 오른쪽, 위, 아래에 있는 스티커는 사용할 수 없게 된다. + * 모든 스티커를 붙일 수 없게된 상냥이는 각 스티커에 점수를 매기고, 점수의 합이 최대가 되게 스티커를 떼어내려고 한다. 먼저, 그림 (b)와 같이 각 스티커에 점수를 매겼다. 상냥이가 뗄 수 있는 스티커의 점수의 최댓값을 구하는 프로그램을 작성하시오. 즉, 2n개의 스티커 중에서 점수의 합이 최대가 되면서 서로 변을 공유 하지 않는 스티커 집합을 구해야 한다. + * 위의 그림의 경우에 점수가 50, 50, 100, 60인 스티커를 고르면, 점수는 260이 되고 이 것이 최대 점수이다. 가장 높은 점수를 가지는 두 스티커 (100과 70)은 변을 공유하기 때문에, 동시에 뗄 수 없다. + * + * ? 입력 & 파싱 + * 첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 n (1 ≤ n ≤ 100,000)이 주어진다. 다음 두 줄에는 n개의 정수가 주어지며, 각 정수는 그 위치에 해당하는 스티커의 점수이다. 연속하는 두 정수 사이에는 빈 칸이 하나 있다. 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다. + * + * 2 -> t + * 5 -> n + * 50 10 100 20 40 -> sticker[0][1] ~ sticker[0][n] + * 30 50 70 10 60 -> sticker[1][1] ~ sticker[1][n] + * 7 -> n + * 10 30 10 50 100 20 40 -> sticker[0][1] ~ sticker[0][n] + * 20 40 30 50 60 20 80 -> sticker[1][1] ~ sticker[1][n] + * + * ? 출력 + * 각 테스트 케이스 마다, 2n개의 스티커 중에서 두 변을 공유하지 않는 스티커 점수의 최댓값을 출력한다. + * + * 260 + * 290 + * + * ? 채점 결과 + * * 시간: 600ms + * * 메모리: 125MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Silver.I; + +import java.io.*; +import java.util.StringTokenizer; + +public class S1_9465 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[][] sticker; + + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); // test case 개수 + StringBuffer sb = new StringBuffer(); // 출력문 + + // * 0. t번동안 + for (int i = 0; i < t; i++) { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) + if (n == 1) { // * n이 1인 경우 스티커 두개 중 max값 추가 + sb.append(Math.max(sticker[0][1], sticker[1][1]) + "\n"); + } else { // * n이 1이 아닌 경우 DP(Tabulation: Bottom-Up) 실행 + sb.append(dp() + "\n"); + } + } + + // * 3. 출력 + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // ! DP(Tabulation: Bottom-Up) + public static int dp() { + int[][] table = new int[2][n+1]; + for (int i = 0; i < 2; i++) { + table[i] = sticker[i].clone(); + } + + + for (int j = 2; j <= n; j++) { + for (int i = 0; i < 2; i++) { + table[i][j] = Math.max(table[i][j], + Math.max(table[i^1][j-1], table[i^1][j-2]) + sticker[i][j]); + } + } + + return Math.max(table[0][n], table[1][n]); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + sticker = new int[2][n+1]; + for (int i = 0; i < 2; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 1; j <= n; j++) { + sticker[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 19c029859bb15e768864423cef1550755b0ea845 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 6 Sep 2022 11:48:55 +0900 Subject: [PATCH 060/163] =?UTF-8?q?[BOJ-2293-JAVA]=20=EB=8F=99=EC=A0=841?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2293.java | 94 ++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2293.java diff --git a/java/BOJ/Gold/V/G5_2293.java b/java/BOJ/Gold/V/G5_2293.java new file mode 100644 index 0000000..84065ac --- /dev/null +++ b/java/BOJ/Gold/V/G5_2293.java @@ -0,0 +1,94 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2293 + * + * ? 제목: 동전 1 + * ? 시간 제한: 0.5초 + * ? 메모리 제한: 4MB + * + * ? 문제 + * n가지 종류의 동전이 있다. 각각의 동전이 나타내는 가치는 다르다. 이 동전을 적당히 사용해서, 그 가치의 합이 k원이 되도록 하고 싶다. 그 경우의 수를 구하시오. 각각의 동전은 몇 개라도 사용할 수 있다. + * 사용한 동전의 구성이 같은데, 순서만 다른 것은 같은 경우이다. + * + * ? 입력 & 파싱 + * 첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다. + * + * 3 10 -> n k + * 1 -> coins[0] + * 2 ... + * 5 -> coins[n-1] + * + * ? 출력 + * 첫째 줄에 경우의 수를 출력한다. 경우의 수는 2^31보다 작다. + * + * 10 + * + * ? 채점 결과 + * * 시간: 96ms + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G5_2293 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, k; + static int[] coins; + + // * 초기 설정 + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. Start Case 설정 + for (int i = 1; i <= k; i++) { + dp[0][i] = (i % coins[0] == 0) ? 1 : 0; + } + + // * 3. DP(Tabulation: Bottom-Up) + for (int i = 1; i < n; i++) { + for (int j = 1; j <= k; j++) { + if (j >= coins[i]) { + if (j == coins[i]) { + dp[i][j] = dp[i-1][j] + 1; + } else { + dp[i][j] = dp[i-1][j] + dp[i][j-coins[i]]; + } + } else { + dp[i][j] = dp[i-1][j]; + } + } + } + + // * 4. 정답 출력 + System.out.println(dp[n-1][k]); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + coins = new int[n]; + dp = new int[n][k+1]; + + for (int i = 0; i < n; i++) { + coins[i] = Integer.parseInt(br.readLine()); + } + + Arrays.sort(coins); + } + +} From d8a8fcce21e64525f5fb37ec625c35e6a8511389 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 6 Sep 2022 11:49:11 +0900 Subject: [PATCH 061/163] =?UTF-8?q?[BOJ-11057-JAVA]=20=EC=98=A4=EB=A5=B4?= =?UTF-8?q?=EB=A7=89=20=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_11057.java | 66 +++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_11057.java diff --git a/java/BOJ/Silver/I/S1_11057.java b/java/BOJ/Silver/I/S1_11057.java new file mode 100644 index 0000000..8a80d1b --- /dev/null +++ b/java/BOJ/Silver/I/S1_11057.java @@ -0,0 +1,66 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11057 + * + * ? 제목: 오르막 수 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 오르막 수는 수의 자리가 오름차순을 이루는 수를 말한다. 이때, 인접한 수가 같아도 오름차순으로 친다. + * 예를 들어, 2234와 3678, 11119는 오르막 수이지만, 2232, 3676, 91111은 오르막 수가 아니다. + * 수의 길이 N이 주어졌을 때, 오르막 수의 개수를 구하는 프로그램을 작성하시오. 수는 0으로 시작할 수 있다. + * + * ? 입력 + * 첫째 줄에 N (1 ≤ N ≤ 1,000)이 주어진다. + * + * 2 + * + * ? 출력 + * 첫째 줄에 길이가 N인 오르막 수의 개수를 10,007로 나눈 나머지를 출력한다. + * + * 55 + * + * ? 채점 결과 + * * 시간: 76ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S1_11057 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + 초기 설정 + int n = Integer.parseInt(br.readLine()); + int div = 10_007; + + // * 2. DP Table 초기화 + Start Case 설정 + int[][] dp = new int[10][n+1]; + for (int i = 0; i < 10; i++) { + dp[i][1] = 1; + } + + // * 3. DP(Tabulation: Bottom-Up) + for (int j = 1; j < n; j++) { + for (int i = 0; i < 10; i++) { + for (int k = i; k < 10; k++) { + dp[k][j+1] = (dp[k][j+1] % div + dp[i][j] % div ) % div; + } + } + } + + // * 4. 정답 계산 및 출력 + int answer = 0; + for (int i = 0; i < 10; i++) { + answer = (answer % div + dp[i][n] % div) % div; + } + System.out.println(answer); + } +} From ae81fcdf600d040054b6c66b9ffc9ae47df0b62b Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 7 Sep 2022 12:33:17 +0900 Subject: [PATCH 062/163] =?UTF-8?q?[BOJ-11051-JAVA]=20=EC=9D=B4=ED=95=AD?= =?UTF-8?q?=EA=B3=84=EC=88=982?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/III/S3_11051.java | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 java/BOJ/Silver/III/S3_11051.java diff --git a/java/BOJ/Silver/III/S3_11051.java b/java/BOJ/Silver/III/S3_11051.java new file mode 100644 index 0000000..8afc7bd --- /dev/null +++ b/java/BOJ/Silver/III/S3_11051.java @@ -0,0 +1,69 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11051 + * + * ? 제목: 이항 계수 2 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 자연수 \(N\)과 정수 \(K\)가 주어졌을 때 이항 계수 + * \(\binom{N}{K}\)를 10,007로 나눈 나머지를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 \(N\)과 \(K\)가 주어진다. (1 ≤ \(N\) ≤ 1,000, 0 ≤ \(K\) ≤ \(N\)) + * + * 5 2 -> n k + * + * ? 출력 + * ( N ) + * ( K ) + * 를 10,007로 나눈 나머지를 출력한다. + * + * 10 + * + * ? 채점 결과 + * * 시간: 96ms + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class S3_11051 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + st = new StringTokenizer(br.readLine()); + int n = Integer.parseInt(st.nextToken()); + int k = Integer.parseInt(st.nextToken()); + + // * 초기 설정 + int div = 10_007; + + // * 2. DP Table 초기화, Start Case 설정 + int[][] dp = new int[n+1][n+1]; + dp[0][0] = 1; + + // * 3. DP(Tabulation: Bottom-Up) - 파스칼의 삼각형(이항계수) + for (int i = 1; i <= n; i++) { + for (int j = 0; j <= i; j++) { + if (j == 0 || j == n) { + dp[i][j] = 1; + } else { + dp[i][j] = (dp[i-1][j-1] % div + dp[i-1][j] % div) % div; + } + } + } + + // * 4. 정답 출력 + System.out.println(dp[n][k]); + } +} From 50092a8047eaa3069c82d1ffa02fc8ca45b065d6 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 7 Sep 2022 15:54:22 +0900 Subject: [PATCH 063/163] =?UTF-8?q?[BOJ-11054-JAVA]=20=EA=B0=80=EC=9E=A5?= =?UTF-8?q?=20=EA=B8=B4=20=EB=B0=94=EC=9D=B4=ED=86=A0=EB=8B=89=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=EC=88=98=EC=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_11054.java | 116 +++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_11054.java diff --git a/java/BOJ/Gold/IV/G4_11054.java b/java/BOJ/Gold/IV/G4_11054.java new file mode 100644 index 0000000..52baf05 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_11054.java @@ -0,0 +1,116 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11054 + * + * ? 제목: 가장 긴 바이토닉 부분 수열 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다. + * 예를 들어, {10, 20, 30, 25, 20}과 {10, 20, 30, 40}, {50, 40, 25, 10} 은 바이토닉 수열이지만, {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다. + * 수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000) + * + * 10 -> n + * 1 5 2 1 4 3 4 5 2 1 -> arr[0] ~ arr[n-1] & reverseArr[n-1] ~ reverseArr[0] + * + * ? 출력 + * 첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다. + * + * 7 + * + * ? 채점 결과 + * * 시간: 84ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G4_11054 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr; + static int[] reverseArr; + + // * 초기 설정 + static int[] LIS; + static int[] REVERSE_LIS; + static int max = 0; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + getLIS(arr, LIS); // * 2. 정방향 LIS + getLIS(reverseArr, REVERSE_LIS); // * 3. 역방향 LIS + + // * 4. 각 인덱스 위치에서의 정,역방향 LIS 길이의 값의 최댓값 비교 + for (int i = 0; i < n; i++) { + max = Math.max(max, LIS[i] + REVERSE_LIS[n-i-1] + 1); + } + + // * 5. 출력 + System.out.println(max); + } + + // * DP(Tabulation: Bottom-Up) - LIS + Binary Search + public static void getLIS(int[] numList, int[] lis) { + int[] lisNum = new int[n]; + + int p = 1; + lisNum[0] = numList[0]; + lis[0] = 0; + + for (int i = 0; i < n; i++) { + if (lisNum[p-1] < numList[i]) { + lis[i] = p; + lisNum[p++] = numList[i]; + } else { + int left = 0; + int right = p - 1; + + while (left <= right) { + int mid = (left + right) / 2; + + if (lisNum[mid] == numList[i]) { + left = mid; + break; + } else if (lisNum[mid] < numList[i]) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + lis[i] = left; + lisNum[left] = numList[i]; + } + } + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + LIS = new int[n]; + REVERSE_LIS = new int[n]; + arr = new int[n]; + reverseArr = new int[n]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + reverseArr[n-i-1] = arr[i]; + } + } +} From 804f3d9aeca0e6479e863e5d666cb837e348d7f1 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 8 Sep 2022 11:31:25 +0900 Subject: [PATCH 064/163] =?UTF-8?q?[BOJ-2294-JAVA]=20=EB=8F=99=EC=A0=842?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2294.java | 99 ++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2294.java diff --git a/java/BOJ/Gold/V/G5_2294.java b/java/BOJ/Gold/V/G5_2294.java new file mode 100644 index 0000000..cf9b915 --- /dev/null +++ b/java/BOJ/Gold/V/G5_2294.java @@ -0,0 +1,99 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2294 + * + * ? 제목: 동전 2 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * n가지 종류의 동전이 있다. 이 동전들을 적당히 사용해서, 그 가치의 합이 k원이 되도록 하고 싶다. 그러면서 동전의 개수가 최소가 되도록 하려고 한다. 각각의 동전은 몇 개라도 사용할 수 있다. + * 사용한 동전의 구성이 같은데, 순서만 다른 것은 같은 경우이다. + * + * ? 입력 & 파싱 + * 첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다. 가치가 같은 동전이 여러 번 주어질 수도 있다. + * + * 3 15 -> n k + * 1 -> HashSet 삽입 + * 5 + * 12 + * + * ? 출력 + * 첫째 줄에 사용한 동전의 최소 개수를 출력한다. 불가능한 경우에는 -1을 출력한다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 0.1초 + * * 메모리: 16MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashSet; +import java.util.StringTokenizer; + +public class G5_2294 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, k; + static HashSet coins; + + // * 초기 설정 + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) + int p = 0; + for (int coin : coins) { + // * 가장 단위가 작은 동전일 때 + if (p == 0) { + for (int j = 1; j * coin <= k; j++) { + dp[p][j * coin] = j; + } + p++; + continue; + } + + for (int j = 0; j <= k; j++) { + if (j < coin) { + dp[p][j] = dp[p-1][j]; + } else { + dp[p][j] = Math.min(dp[p-1][j], dp[p][j-coin] + 1); + } + } + p++; + } + + // * 3. 정답 출력(불가능한 경우 값이 100000이므로 그때는 -1) + System.out.println(dp[dp.length-1][k] == 100000 ? -1 : dp[dp.length-1][k]); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + coins = new HashSet<>(); + for (int i = 0; i < n; i++) { + coins.add(Integer.parseInt(br.readLine())); + } + + dp = new int[coins.size()][k+1]; + + for (int i = 0; i < dp.length; i++) { + for (int j = 1; j <= k; j++) { + dp[i][j] = 100000; // 충분히 큰 수로 DP 테이블 초기화 + } + } + } +} From 551675e03bd1b62a6d9320fa0609eeabcbe12a16 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 8 Sep 2022 11:44:48 +0900 Subject: [PATCH 065/163] =?UTF-8?q?[BOJ-11048-JAVA]=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_11048.java | 96 +++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_11048.java diff --git a/java/BOJ/Silver/I/S1_11048.java b/java/BOJ/Silver/I/S1_11048.java new file mode 100644 index 0000000..b91bf9a --- /dev/null +++ b/java/BOJ/Silver/I/S1_11048.java @@ -0,0 +1,96 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11048 + * + * ? 제목: 이동하기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다. + * 준규는 현재 (1, 1)에 있고, (N, M)으로 이동하려고 한다. 준규가 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 이동할 수 있고, 각 방을 방문할 때마다 방에 놓여져있는 사탕을 모두 가져갈 수 있다. 또, 미로 밖으로 나갈 수는 없다. + * 준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수의 최댓값을 구하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 미로의 크기 N, M이 주어진다. (1 ≤ N, M ≤ 1,000) + * 둘째 줄부터 N개 줄에는 총 M개의 숫자가 주어지며, r번째 줄의 c번째 수는 (r, c)에 놓여져 있는 사탕의 개수이다. 사탕의 개수는 0보다 크거나 같고, 100보다 작거나 같다. + * + * 3 4 -> n m + * 1 2 3 4 -> arr[0][0] ~ arr[0][m-1] + * 0 0 0 5 + * 9 8 7 6 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 첫째 줄에 준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다. + * + * 31 + * + * ? 채점 결과 + * * 시간: 0.5초 + * * 메모리: 75MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class S1_11048 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[][] arr; + + // * 초기 설정 + static int[][] dp; + + // * 방향 설정 + static int[] dx = {1, 1, 0}; + static int[] dy = {1, 0, 1}; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + for (int k = 0; k < 3; k++) { + int ny = i + dy[k]; + int nx = j + dx[k]; + + if (ny < 0 || nx < 0 || ny >= n || nx >= m) { + continue; + } + + dp[ny][nx] = Math.max(dp[ny][nx], dp[i][j] + arr[ny][nx]); + } + } + } + + // * 3. 출력 + System.out.println(dp[n-1][m-1]); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n][m]; + dp = new int[n][m]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + dp[i][j] = arr[i][j]; + } + } + } +} From 6ff97e5bdd168354602cb36f1a3223febff5ed05 Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 9 Sep 2022 11:44:57 +0900 Subject: [PATCH 066/163] =?UTF-8?q?[BOJ-2225-JAVA]=20=ED=95=A9=EB=B6=84?= =?UTF-8?q?=ED=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2225.java | 76 ++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2225.java diff --git a/java/BOJ/Gold/V/G5_2225.java b/java/BOJ/Gold/V/G5_2225.java new file mode 100644 index 0000000..6e0d3f8 --- /dev/null +++ b/java/BOJ/Gold/V/G5_2225.java @@ -0,0 +1,76 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2225 + * + * ? 제목: 합분해 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 0부터 N까지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수를 구하는 프로그램을 작성하시오. + * 덧셈의 순서가 바뀐 경우는 다른 경우로 센다(1+2와 2+1은 서로 다른 경우). 또한 한 개의 수를 여러 번 쓸 수도 있다. + * + * ? 입력 & 파싱 + * 첫째 줄에 두 정수 N(1 ≤ N ≤ 200), K(1 ≤ K ≤ 200)가 주어진다. + * + * 20 2 -> n k + * + * ? 출력 + * 첫째 줄에 답을 1,000,000,000으로 나눈 나머지를 출력한다. + * + * 21 + * + * ? 채점 결과 + * * 시간: 0.156초 + * * 메모리: 12MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G5_2225 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, k; + + // * 초기 설정 + static int div = 1_000_000_000; + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. Start Case 설정 + for (int i = 0; i <= n; i++) { + dp[0][i] = 1; + } + + // * 3. DP(Tabulation: Bottom-Up) + for (int i = 1; i < k; i++) { + for (int j = 0; j <= n; j++) { + for (int w = 0; w <= j; w++) { + dp[i][j] = (dp[i][j] % div + dp[i-1][w] % div) % div; + } + } + } + + // * 4. 출력 + System.out.println(dp[k-1][n]); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + + n = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + dp = new int[k][n+1]; // DP 테이블 초기화 + } +} From 94d7954df94ece58d1620be62ab05313a1758f5e Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 9 Sep 2022 11:45:20 +0900 Subject: [PATCH 067/163] =?UTF-8?q?[BOJ-11660-JAVA]=20=EA=B5=AC=EA=B0=84?= =?UTF-8?q?=20=ED=95=A9=20=EA=B5=AC=ED=95=98=EA=B8=B0=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_11660.java | 131 ++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_11660.java diff --git a/java/BOJ/Silver/I/S1_11660.java b/java/BOJ/Silver/I/S1_11660.java new file mode 100644 index 0000000..8eceb59 --- /dev/null +++ b/java/BOJ/Silver/I/S1_11660.java @@ -0,0 +1,131 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11660 + * + * ? 제목: 구간 합 구하기 5 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * N×N개의 수가 N×N 크기의 표에 채워져 있다. (x1, y1)부터 (x2, y2)까지 합을 구하는 프로그램을 작성하시오. (x, y)는 x행 y열을 의미한다. + * 예를 들어, N = 4이고, 표가 아래와 같이 채워져 있는 경우를 살펴보자. + * + * 1 2 3 4 + * 2 3 4 5 + * 3 4 5 6 + * 4 5 6 7 + * 여기서 (2, 2)부터 (3, 4)까지 합을 구하면 3+4+5+4+5+6 = 27이고, (4, 4)부터 (4, 4)까지 합을 구하면 7이다. + * 표에 채워져 있는 수와 합을 구하는 연산이 주어졌을 때, 이를 처리하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네 개의 정수 x1, y1, x2, y2 가 주어지며, (x1, y1)부터 (x2, y2)의 합을 구해 출력해야 한다. 표에 채워져 있는 수는 1,000보다 작거나 같은 자연수이다. (x1 ≤ x2, y1 ≤ y2) + * + * 4 3 -> n m + * 1 2 3 4 -> arr[0][0] ~ arr[0][n-1] + * 2 3 4 5 + * 3 4 5 6 + * 4 5 6 7 -> arr[n-1][0] ~ arr[n-1][n-1] + * 2 2 3 4 -> test[0] ~ test[0][3] + * 3 4 3 4 + * 1 1 4 4 -> test[m-1][0] ~ test[m-1][3] + * + * ? 출력 + * 총 M줄에 걸쳐 (x1, y1)부터 (x2, y2)까지 합을 구해 출력한다. + * + * 27 + * 6 + * 64 + * + * ? 채점 결과 + * * 시간: 0.724초 + * * 메모리: 144MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Silver.I; + +import java.io.*; +import java.util.StringTokenizer; + +public class S1_11660 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[][] arr; + static int[][] test; + + // * 초기 설정 + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up): 누적합 구하기 + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i-1 >= 0 && j-1 >= 0) { + dp[i][j] = dp[i][j] + dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]; + } else if (i-1 >= 0) { + dp[i][j] += dp[i-1][j]; + } else if (j-1 >= 0) { + dp[i][j] += dp[i][j-1]; + } + } + } + + // * 3. 구간합 구하기(중복제거) + StringBuffer sb = new StringBuffer(); + for (int[] t : test) { + int sum = 0; + if (t[0]-1 >= 0 && t[1]-1 >= 0) { + sum = dp[t[2]][t[3]] + - dp[t[0]-1][t[3]] + - dp[t[2]][t[1]-1] + + dp[t[0]-1][t[1]-1]; + } else if (t[0]-1 >= 0) { + sum = dp[t[2]][t[3]] - dp[t[0]-1][t[3]]; + } else if (t[1]-1 >= 0) { + sum = dp[t[2]][t[3]] - dp[t[2]][t[1]-1]; + } else { + sum = dp[t[2]][t[3]]; + } + sb.append(sum + "\n"); + } + + // * 4. 출력 + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n][n]; + test = new int[m][4]; + dp = new int[n][n]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + dp[i][j] = arr[i][j]; + } + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < 4; j++) { + test[i][j] = Integer.parseInt(st.nextToken()) - 1; + } + } + } +} From ac07518515fe1c0e27402454d1cfc98307a5f66b Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 10 Sep 2022 13:31:45 +0900 Subject: [PATCH 068/163] =?UTF-8?q?[BOJ-2565-JAVA]=20=EC=A0=84=EA=B9=83?= =?UTF-8?q?=EC=A4=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2565.java | 107 +++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2565.java diff --git a/java/BOJ/Gold/V/G5_2565.java b/java/BOJ/Gold/V/G5_2565.java new file mode 100644 index 0000000..285f9a9 --- /dev/null +++ b/java/BOJ/Gold/V/G5_2565.java @@ -0,0 +1,107 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2565 + * + * ? 제목: 전깃줄 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 두 전봇대 A와 B 사이에 하나 둘씩 전깃줄을 추가하다 보니 전깃줄이 서로 교차하는 경우가 발생하였다. 합선의 위험이 있어 이들 중 몇 개의 전깃줄을 없애 전깃줄이 교차하지 않도록 만들려고 한다. + * 예를 들어, < 그림 1 >과 같이 전깃줄이 연결되어 있는 경우 A의 1번 위치와 B의 8번 위치를 잇는 전깃줄, A의 3번 위치와 B의 9번 위치를 잇는 전깃줄, A의 4번 위치와 B의 1번 위치를 잇는 전깃줄을 없애면 남아있는 모든 전깃줄이 서로 교차하지 않게 된다. + * 전깃줄이 전봇대에 연결되는 위치는 전봇대 위에서부터 차례대로 번호가 매겨진다. 전깃줄의 개수와 전깃줄들이 두 전봇대에 연결되는 위치의 번호가 주어질 때, 남아있는 모든 전깃줄이 서로 교차하지 않게 하기 위해 없애야 하는 전깃줄의 최소 개수를 구하는 프로그램을 작성하시오. + * + * ? 입력 * 파싱 + * 첫째 줄에는 두 전봇대 사이의 전깃줄의 개수가 주어진다. 전깃줄의 개수는 100 이하의 자연수이다. 둘째 줄부터 한 줄에 하나씩 전깃줄이 A전봇대와 연결되는 위치의 번호와 B전봇대와 연결되는 위치의 번호가 차례로 주어진다. 위치의 번호는 500 이하의 자연수이고, 같은 위치에 두 개 이상의 전깃줄이 연결될 수 없다. + * + * 8 -> n + * 1 8 -> arr[0][0] arr[0][1] + * 3 9 + * 2 2 + * 4 1 + * 6 4 + * 10 10 + * 9 7 + * 7 6 -> arr[n-1][0] arr[n-1][1] + * + * ? 출력 + * 첫째 줄에 남아있는 모든 전깃줄이 서로 교차하지 않게 하기 위해 없애야 하는 전깃줄의 최소 개수를 출력한다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 0.22초 + * * 메모리: 18MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.V; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G5_2565 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[][] arr; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 (B전봇대를 기준으로 정렬) + int lis = LIS(); // * 2. LIS + System.out.println(n - lis); // * 3. 전봇대 갯수에서 LIS 길이를 뺀 값 출력 + } + + // * LIS + public static int LIS() { + int[] dp = new int[n]; + dp[0] = arr[0][0]; + int p = 1; + + for (int i = 1; i < n; i++) { + if (dp[p-1] < arr[i][0]) { + dp[p++] = arr[i][0]; + } else { + int left = 0; + int right = p-1; + + while (left <= right) { + int mid = (left + right) / 2; + + if (dp[mid] == arr[i][0]) { + break; + } + + if (dp[mid] > arr[i][0]) { + right = mid-1; + } else { + left = mid+1; + } + } + + dp[left] = arr[i][0]; + } + } + + return p; + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n][2]; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + arr[i] = new int[] {a, b}; + } + + Arrays.sort(arr, (a, b) -> a[1] - b[1]); + } +} \ No newline at end of file From e3b3105f83b75a96e24c093cefe4d5062d50d6b9 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 10 Sep 2022 13:32:04 +0900 Subject: [PATCH 069/163] =?UTF-8?q?[BOJ-1309-JAVA]=20=EB=8F=99=EB=AC=BC?= =?UTF-8?q?=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_1309.java | 73 ++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_1309.java diff --git a/java/BOJ/Silver/I/S1_1309.java b/java/BOJ/Silver/I/S1_1309.java new file mode 100644 index 0000000..7a091d2 --- /dev/null +++ b/java/BOJ/Silver/I/S1_1309.java @@ -0,0 +1,73 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * https://www.acmicpc.net/problem/1309 + * + * ? 제목: 동물원 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 어떤 동물원에 가로로 두칸 세로로 N칸인 아래와 같은 우리가 있다. + * 이 동물원에는 사자들이 살고 있는데 사자들을 우리에 가둘 때, 가로로도 세로로도 붙어 있게 배치할 수는 없다. 이 동물원 조련사는 사자들의 배치 문제 때문에 골머리를 앓고 있다. + * 동물원 조련사의 머리가 아프지 않도록 우리가 2*N 배열에 사자를 배치하는 경우의 수가 몇 가지인지를 알아내는 프로그램을 작성해 주도록 하자. 사자를 한 마리도 배치하지 않는 경우도 하나의 경우의 수로 친다고 가정한다. + * + * ? 입력 + * 첫째 줄에 우리의 크기 N(1≤N≤100,000)이 주어진다. + * + * 4 + * + * ? 출력 + * 첫째 줄에 사자를 배치하는 경우의 수를 9901로 나눈 나머지를 출력하여라. + * + * 41 + * + * ? 채점 결과 + * * 시간: 0.092초 + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S1_1309 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + int n = Integer.parseInt(br.readLine()); + + // * 초기 설정 + int div = 9901; + + // * DP 테이블 초기화 + int[][] dp = new int[n+1][3]; + + // * Start Case 설정 + dp[1][0] = 1; + dp[1][1] = 1; + dp[1][2] = 1; + + /* + 0 : 해당 줄에 아무것도 선택하지 않음 + 1 : 해당 줄에 왼쪽을 선택함 + 2 : 해당 줄의 오른쪽을 선택함 + */ + + // * 2. DP(Tabulation: Bottom-Up) + for (int i = 2; i <= n; i++) { + dp[i][0] = ((dp[i-1][0] % div + dp[i-1][1] % div) % div + dp[i-1][2] % div) % div; + dp[i][1] = (dp[i-1][0] % div + dp[i-1][2]) % div; + dp[i][2] = (dp[i-1][0] % div + dp[i-1][1] % div) % div; + } + + // * 3. 출력 + System.out.println( + ((dp[n][0] % div + dp[n][1] % div) % div + + dp[n][2] % div) % div + ); + } +} From 0fb235c420743d4e34c5e701611c0d055b08dd2f Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 11 Sep 2022 13:19:43 +0900 Subject: [PATCH 070/163] =?UTF-8?q?[BOJ-9655-JAVA]=20=EB=8F=8C=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/V/S5_9655.java | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 java/BOJ/Silver/V/S5_9655.java diff --git a/java/BOJ/Silver/V/S5_9655.java b/java/BOJ/Silver/V/S5_9655.java new file mode 100644 index 0000000..28977ff --- /dev/null +++ b/java/BOJ/Silver/V/S5_9655.java @@ -0,0 +1,43 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/9655 + * + * ? 제목: 돌 게임 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 돌 게임은 두 명이서 즐기는 재밌는 게임이다. + * 탁자 위에 돌 N개가 있다. 상근이와 창영이는 턴을 번갈아가면서 돌을 가져가며, 돌은 1개 또는 3개 가져갈 수 있다. 마지막 돌을 가져가는 사람이 게임을 이기게 된다. + * 두 사람이 완벽하게 게임을 했을 때, 이기는 사람을 구하는 프로그램을 작성하시오. 게임은 상근이가 먼저 시작한다. + * + * ? 입력 + * 첫째 줄에 N이 주어진다. (1 ≤ N ≤ 1000) + * + * 5 + * + * ? 출력 + * 상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다. + * + * SK + * + * ? 채점 결과 + * * 시간: 0.076ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S5_9655 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static void main(String[] args) throws IOException { + int n = Integer.parseInt(br.readLine()); + System.out.println(n % 2 == 0 ? "CY" : "SK"); + } +} From 050d15db58000e6a4bb949eac5a5e4403dd332cc Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 11 Sep 2022 13:48:41 +0900 Subject: [PATCH 071/163] =?UTF-8?q?[BOJ-1890-JAVA]=20=EC=A0=90=ED=94=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_1890.java | 91 ++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_1890.java diff --git a/java/BOJ/Silver/I/S1_1890.java b/java/BOJ/Silver/I/S1_1890.java new file mode 100644 index 0000000..a9b1543 --- /dev/null +++ b/java/BOJ/Silver/I/S1_1890.java @@ -0,0 +1,91 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1890 + * + * ? 제목: 점프 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * N×N 게임판에 수가 적혀져 있다. 이 게임의 목표는 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 점프를 해서 가는 것이다. + * 각 칸에 적혀있는 수는 현재 칸에서 갈 수 있는 거리를 의미한다. 반드시 오른쪽이나 아래쪽으로만 이동해야 한다. 0은 더 이상 진행을 막는 종착점이며, 항상 현재 칸에 적혀있는 수만큼 오른쪽이나 아래로 가야 한다. 한 번 점프를 할 때, 방향을 바꾸면 안 된다. 즉, 한 칸에서 오른쪽으로 점프를 하거나, 아래로 점프를 하는 두 경우만 존재한다. + * 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 이동할 수 있는 경로의 개수를 구하는 프로그램을 작성하시오. + * + * ? 입력 + * 첫째 줄에 게임 판의 크기 N (4 ≤ N ≤ 100)이 주어진다. 그 다음 N개 줄에는 각 칸에 적혀져 있는 수가 N개씩 주어진다. 칸에 적혀있는 수는 0보다 크거나 같고, 9보다 작거나 같은 정수이며, 가장 오른쪽 아래 칸에는 항상 0이 주어진다. + * + * 4 -> n + * 2 3 3 1 -> arr[0][0] ~ arr[0][n-1] + * 1 2 1 3 + * 1 2 3 1 + * 3 1 1 0 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 문제의 규칙에 맞게 갈 수 있는 경로의 개수를 출력한다. 경로의 개수는 263-1보다 작거나 같다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 0.08초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Silver.I; + +import java.io.*; +import java.util.StringTokenizer; + +public class S1_1890 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[][] arr; + + // * 초기 설정 + static long[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + dp[0][0] = 1L; // * Start Case 설정 + + // * 2. DP(Tabulation: Bottom-Up) + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + int k = arr[i][j]; + + if (k == 0) { + break; + } + + if (i+k < n) { + dp[i+k][j] += dp[i][j]; + } + + if (j+k < n) { + dp[i][j+k] += dp[i][j]; + } + } + } + + // * 3. 출력 + System.out.println(dp[n-1][n-1]); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n][n]; + dp = new long[n][n]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 33800ae76e86f4a0cce60003298f2ab7e00e4919 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 11 Sep 2022 14:28:42 +0900 Subject: [PATCH 072/163] =?UTF-8?q?[BOJ-14002-JAVA]=20=EA=B0=80=EC=9E=A5?= =?UTF-8?q?=20=EA=B8=B4=20=EC=A6=9D=EA=B0=80=ED=95=98=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=97=B4=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_14002.java | 125 +++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_14002.java diff --git a/java/BOJ/Gold/IV/G4_14002.java b/java/BOJ/Gold/IV/G4_14002.java new file mode 100644 index 0000000..99b0997 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_14002.java @@ -0,0 +1,125 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14002 + * + * ? 제목: 가장 긴 증가하는 부분 수열 4 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. + * 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다. + * + * ? 입력 + * 첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다. + * 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000) + * + * ? 출력 + * 첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다. + * 둘째 줄에는 가장 긴 증가하는 부분 수열을 출력한다. 그러한 수열이 여러가지인 경우 아무거나 출력한다. + * + * ? 채점 결과 + * * 시간: 0.08초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.IV; + +import java.io.*; +import java.util.StringTokenizer; + +public class G4_14002 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int[] dp; + static int[] index; + static int[] lis; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + LIS(); // * 2. DP(Tabulation: Bottom-Up): LIS + getLIS(); // * 3. LIS 배열 찾기 + + // * 4. 출력 + bw.write(String.valueOf(lis.length) + "\n"); + for (int i = 0; i < lis.length; i++) { + bw.write(String.valueOf(lis[i]) + " "); + } + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + st = new StringTokenizer(br.readLine()); + + arr = new int[n]; + dp = new int[n]; + index = new int[n]; + + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + } + + // LIS + public static void LIS() { + int p = 1; + dp[0] = arr[0]; + index[0] = 0; + + for (int i = 0; i < n; i++) { + if (dp[p-1] < arr[i]) { + index[i] = p; + dp[p++] = arr[i]; + } else { + int left = 0; + int right = p-1; + + while (left <= right) { + int mid = (left + right) / 2; + + if (dp[mid] == arr[i]) { + left = mid; + break; + } + + if (dp[mid] > arr[i]) { + right = mid-1; + } else { + left = mid+1; + } + } + + dp[left] = arr[i]; + index[i] = left; + } + } + + lis = new int[p]; // LIS 배열 크기 설정 + } + + // LIS 배열 찾기 + public static void getLIS() { + int p = lis.length - 1; + int idx = n-1; + + while (idx >= 0) { + if (index[idx] == p) { + lis[p--] = arr[idx]; + } + idx--; + } + } +} From bd6ff706c1300ad21baa687b96e779559f2a553a Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 12 Sep 2022 11:03:23 +0900 Subject: [PATCH 073/163] =?UTF-8?q?[BOJ-2096-JAVA]=20=EB=82=B4=EB=A0=A4?= =?UTF-8?q?=EA=B0=80=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2096.java | 96 ++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2096.java diff --git a/java/BOJ/Gold/V/G5_2096.java b/java/BOJ/Gold/V/G5_2096.java new file mode 100644 index 0000000..aa2f10f --- /dev/null +++ b/java/BOJ/Gold/V/G5_2096.java @@ -0,0 +1,96 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2096 + * + * ? 제목: 내려가기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 4MB + * + * ? 문제 + * N줄에 0 이상 9 이하의 숫자가 세 개씩 적혀 있다. 내려가기 게임을 하고 있는데, 이 게임은 첫 줄에서 시작해서 마지막 줄에서 끝나게 되는 놀이이다. + * 먼저 처음에 적혀 있는 세 개의 숫자 중에서 하나를 골라서 시작하게 된다. 그리고 다음 줄로 내려가는데, 다음 줄로 내려갈 때에는 다음과 같은 제약 조건이 있다. 바로 아래의 수로 넘어가거나, 아니면 바로 아래의 수와 붙어 있는 수로만 이동할 수 있다는 것이다. 이 제약 조건을 그림으로 나타내어 보면 다음과 같다. + * 별표는 현재 위치이고, 그 아랫 줄의 파란 동그라미는 원룡이가 다음 줄로 내려갈 수 있는 위치이며, 빨간 가위표는 원룡이가 내려갈 수 없는 위치가 된다. 숫자표가 주어져 있을 때, 얻을 수 있는 최대 점수, 최소 점수를 구하는 프로그램을 작성하시오. 점수는 원룡이가 위치한 곳의 수의 합이다. + * + * ? 입력 + * 첫째 줄에 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 숫자가 세 개씩 주어진다. 숫자는 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 중의 하나가 된다. + * + * 3 -> n + * 1 2 3 -> arr[0][0] ~ arr[0][2] + * 4 5 6 + * 4 9 0 -> arr[n-1][0] ~ arr[n-1][2] + * + * ? 출력 + * 첫째 줄에 얻을 수 있는 최대 점수와 최소 점수를 띄어서 출력한다. + * + * 18 6 + * + * ? 채점 결과 + * * 시간: 0.54초 + * * 메모리: 57MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G5_2096 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[][] arr; + + // * 초기 설정 + static int[][] maxDp; + static int[][] minDp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) + for (int i = 1; i < n; i++) { + // * 내려가기 최댓값 DP + maxDp[i][0] = Math.max(maxDp[i-1][0], maxDp[i-1][1]) + arr[i][0]; + maxDp[i][1] = Math.max(maxDp[i-1][0], Math.max(maxDp[i-1][1], maxDp[i-1][2])) + arr[i][1]; + maxDp[i][2] = Math.max(maxDp[i-1][1], maxDp[i-1][2]) + arr[i][2]; + + // * 내려가기 최솟값 DP + minDp[i][0] = Math.min(minDp[i-1][0], minDp[i-1][1]) + arr[i][0]; + minDp[i][1] = Math.min(minDp[i-1][0], Math.min(minDp[i-1][1], minDp[i-1][2])) + arr[i][1]; + minDp[i][2] = Math.min(minDp[i-1][1], minDp[i-1][2]) + arr[i][2]; + } + + // * 3. 정답 출력 + int max = Arrays.stream(maxDp[n-1]).max().getAsInt(); + int min = Arrays.stream(minDp[n-1]).min().getAsInt(); + + bw.write(max + " " + min); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n][3]; + maxDp = new int[n][3]; + minDp = new int[n][3]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < 3; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + maxDp[i][j] = arr[i][j]; + minDp[i][j] = arr[i][j]; + } + } + } +} From 39c47b3b80af969c60c58d37c230507b9022f99b Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 13 Sep 2022 15:16:29 +0900 Subject: [PATCH 074/163] =?UTF-8?q?[BOJ-11066-JAVA]=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=ED=95=A9=EC=B9=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_11066.java | 92 +++++++++++++++++++++ java/BOJ/Gold/III/G3_11066_RECURSE.java | 104 ++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_11066.java create mode 100644 java/BOJ/Gold/III/G3_11066_RECURSE.java diff --git a/java/BOJ/Gold/III/G3_11066.java b/java/BOJ/Gold/III/G3_11066.java new file mode 100644 index 0000000..c4bbe2d --- /dev/null +++ b/java/BOJ/Gold/III/G3_11066.java @@ -0,0 +1,92 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11066 + * + * ? 제목: 파일 합치기 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 소설가인 김대전은 소설을 여러 장(chapter)으로 나누어 쓰는데, 각 장은 각각 다른 파일에 저장하곤 한다. 소설의 모든 장을 쓰고 나서는 각 장이 쓰여진 파일을 합쳐서 최종적으로 소설의 완성본이 들어있는 한 개의 파일을 만든다. 이 과정에서 두 개의 파일을 합쳐서 하나의 임시파일을 만들고, 이 임시파일이나 원래의 파일을 계속 두 개씩 합쳐서 소설의 여러 장들이 연속이 되도록 파일을 합쳐나가고, 최종적으로는 하나의 파일로 합친다. 두 개의 파일을 합칠 때 필요한 비용(시간 등)이 두 파일 크기의 합이라고 가정할 때, 최종적인 한 개의 파일을 완성하는데 필요한 비용의 총 합을 계산하시오. + * 예를 들어, C1, C2, C3, C4가 연속적인 네 개의 장을 수록하고 있는 파일이고, 파일 크기가 각각 40, 30, 30, 50 이라고 하자. 이 파일들을 합치는 과정에서, 먼저 C2와 C3를 합쳐서 임시파일 X1을 만든다. 이때 비용 60이 필요하다. 그 다음으로 C1과 X1을 합쳐 임시파일 X2를 만들면 비용 100이 필요하다. 최종적으로 X2와 C4를 합쳐 최종파일을 만들면 비용 150이 필요하다. 따라서, 최종의 한 파일을 만드는데 필요한 비용의 합은 60+100+150=310 이다. 다른 방법으로 파일을 합치면 비용을 줄일 수 있다. 먼저 C1과 C2를 합쳐 임시파일 Y1을 만들고, C3와 C4를 합쳐 임시파일 Y2를 만들고, 최종적으로 Y1과 Y2를 합쳐 최종파일을 만들 수 있다. 이때 필요한 총 비용은 70+80+150=300 이다. + * 소설의 각 장들이 수록되어 있는 파일의 크기가 주어졌을 때, 이 파일들을 하나의 파일로 합칠 때 필요한 최소비용을 계산하는 프로그램을 작성하시오. + * + * ? 입력 + * 프로그램은 표준 입력에서 입력 데이터를 받는다. 프로그램의 입력은 T개의 테스트 데이터로 이루어져 있는데, T는 입력의 맨 첫 줄에 주어진다.각 테스트 데이터는 두 개의 행으로 주어지는데, 첫 행에는 소설을 구성하는 장의 수를 나타내는 양의 정수 K (3 ≤ K ≤ 500)가 주어진다. 두 번째 행에는 1장부터 K장까지 수록한 파일의 크기를 나타내는 양의 정수 K개가 주어진다. 파일의 크기는 10,000을 초과하지 않는다. + * + * 2 -> t + * 4 -> n + * 40 30 30 50 -> arr[1] ~ arr[n] + * 15 -> n + * 1 21 3 4 5 35 5 4 3 5 98 21 14 17 32 -> arr[1] ~ arr[n] + * + * ? 출력 + * 프로그램은 표준 출력에 출력한다. 각 테스트 데이터마다 정확히 한 행에 출력하는데, 모든 장을 합치는데 필요한 최소비용을 출력한다. + * + * 300 + * 864 + * + * ? 채점 결과 + * * 시간: 0.32초 + * * 메모리: 18MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.StringTokenizer; + +public class G3_11066 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr, sum; + + // * DP Table + static int[][] dp; + + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); // Test Case 개수 + for (int i = 0; i < t; i++) { + input(); // * 1. 입력 받기 + bw.write(mergeFile() + "\n"); // * 2. DP(Tabulation: Bottom-Up) + 3. 출력 + } + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n+1]; + sum = new int[n+1]; + dp = new int[n+1][n+1]; + + st = new StringTokenizer(br.readLine()); + for (int i = 1; i <= n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + sum[i] = sum[i-1] + arr[i]; + } + } + + // * DP + public static int mergeFile() { + for (int i = 1; i <= n; i++) { + for (int j = 1; i+j <= n; j++) { + dp[j][i+j] = Integer.MAX_VALUE; + for (int k = j; k < i+j; k++) { + dp[j][i+j] = Math.min(dp[j][i+j], dp[j][k] + dp[k+1][i+j] + sum[i+j] - sum[j-1]); + } + } + } + + return dp[1][n]; + } +} diff --git a/java/BOJ/Gold/III/G3_11066_RECURSE.java b/java/BOJ/Gold/III/G3_11066_RECURSE.java new file mode 100644 index 0000000..a00190a --- /dev/null +++ b/java/BOJ/Gold/III/G3_11066_RECURSE.java @@ -0,0 +1,104 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11066 + * + * ? 제목: 파일 합치기 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 소설가인 김대전은 소설을 여러 장(chapter)으로 나누어 쓰는데, 각 장은 각각 다른 파일에 저장하곤 한다. 소설의 모든 장을 쓰고 나서는 각 장이 쓰여진 파일을 합쳐서 최종적으로 소설의 완성본이 들어있는 한 개의 파일을 만든다. 이 과정에서 두 개의 파일을 합쳐서 하나의 임시파일을 만들고, 이 임시파일이나 원래의 파일을 계속 두 개씩 합쳐서 소설의 여러 장들이 연속이 되도록 파일을 합쳐나가고, 최종적으로는 하나의 파일로 합친다. 두 개의 파일을 합칠 때 필요한 비용(시간 등)이 두 파일 크기의 합이라고 가정할 때, 최종적인 한 개의 파일을 완성하는데 필요한 비용의 총 합을 계산하시오. + * 예를 들어, C1, C2, C3, C4가 연속적인 네 개의 장을 수록하고 있는 파일이고, 파일 크기가 각각 40, 30, 30, 50 이라고 하자. 이 파일들을 합치는 과정에서, 먼저 C2와 C3를 합쳐서 임시파일 X1을 만든다. 이때 비용 60이 필요하다. 그 다음으로 C1과 X1을 합쳐 임시파일 X2를 만들면 비용 100이 필요하다. 최종적으로 X2와 C4를 합쳐 최종파일을 만들면 비용 150이 필요하다. 따라서, 최종의 한 파일을 만드는데 필요한 비용의 합은 60+100+150=310 이다. 다른 방법으로 파일을 합치면 비용을 줄일 수 있다. 먼저 C1과 C2를 합쳐 임시파일 Y1을 만들고, C3와 C4를 합쳐 임시파일 Y2를 만들고, 최종적으로 Y1과 Y2를 합쳐 최종파일을 만들 수 있다. 이때 필요한 총 비용은 70+80+150=300 이다. + * 소설의 각 장들이 수록되어 있는 파일의 크기가 주어졌을 때, 이 파일들을 하나의 파일로 합칠 때 필요한 최소비용을 계산하는 프로그램을 작성하시오. + * + * ? 입력 + * 프로그램은 표준 입력에서 입력 데이터를 받는다. 프로그램의 입력은 T개의 테스트 데이터로 이루어져 있는데, T는 입력의 맨 첫 줄에 주어진다.각 테스트 데이터는 두 개의 행으로 주어지는데, 첫 행에는 소설을 구성하는 장의 수를 나타내는 양의 정수 K (3 ≤ K ≤ 500)가 주어진다. 두 번째 행에는 1장부터 K장까지 수록한 파일의 크기를 나타내는 양의 정수 K개가 주어진다. 파일의 크기는 10,000을 초과하지 않는다. + * + * 2 -> t + * 4 -> n + * 40 30 30 50 -> arr[1] ~ arr[n] + * 15 -> n + * 1 21 3 4 5 35 5 4 3 5 98 21 14 17 32 -> arr[1] ~ arr[n] + * + * ? 출력 + * 프로그램은 표준 출력에 출력한다. 각 테스트 데이터마다 정확히 한 행에 출력하는데, 모든 장을 합치는데 필요한 최소비용을 출력한다. + * + * 300 + * 864 + * + * ? 채점 결과 + * * 시간: 0.68초 + * * 메모리: 20MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G3_11066_RECURSE { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr, sum; + + // * DP Table + static int[][] dp; + + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); // Test Case 개수 + for (int i = 0; i < t; i++) { + input(); // * 1. 입력 받기 + bw.write(mergeFile(1, n) - sum[n] + "\n"); // * 2. DP(Memoization: Top-Down) + 3. 출력 + } + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n+1]; + sum = new int[n+1]; + dp = new int[n+1][n+1]; + + st = new StringTokenizer(br.readLine()); + for (int i = 1; i <= n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + sum[i] = sum[i-1] + arr[i]; + } + + for (int[] d : dp) { + Arrays.fill(d, -1); + } + } + + // * DP + public static int mergeFile(int start, int end) { + if (start == end) { + return arr[start]; + } + + if (dp[start][end] != -1) { + return dp[start][end]; + } + + dp[start][end] = 1_000_000_000; + + for (int i = start; i < end; i++) { + dp[start][end] = Math.min(dp[start][end], mergeFile(start, i) + mergeFile(i+1, end)); + } + + dp[start][end] += sum[end] - sum[start-1]; + + return dp[start][end]; + } +} From 8b7eaef72df1057a66770bd9009a6f1e3aa25ce0 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 14 Sep 2022 21:48:01 +0900 Subject: [PATCH 075/163] =?UTF-8?q?[BOJ-10942-JAVA]=20=ED=8C=B0=EB=A6=B0?= =?UTF-8?q?=EB=93=9C=EB=A1=AC=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_10942.java | 117 +++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_10942.java diff --git a/java/BOJ/Gold/IV/G4_10942.java b/java/BOJ/Gold/IV/G4_10942.java new file mode 100644 index 0000000..0bbea25 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_10942.java @@ -0,0 +1,117 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/10942 + * + * ? 제목: 팰린드롬? + * ? 시간 제한: 2.5초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 명우는 홍준이와 함께 팰린드롬 놀이를 해보려고 한다. + * 먼저, 홍준이는 자연수 N개를 칠판에 적는다. 그 다음, 명우에게 질문을 총 M번 한다. + * 각 질문은 두 정수 S와 E(1 ≤ S ≤ E ≤ N)로 나타낼 수 있으며, S번째 수부터 E번째 까지 수가 팰린드롬을 이루는지를 물어보며, 명우는 각 질문에 대해 팰린드롬이다 또는 아니다를 말해야 한다. + * 예를 들어, 홍준이가 칠판에 적은 수가 1, 2, 1, 3, 1, 2, 1라고 하자. + * + * S = 1, E = 3인 경우 1, 2, 1은 팰린드롬이다. + * S = 2, E = 5인 경우 2, 1, 3, 1은 팰린드롬이 아니다. + * S = 3, E = 3인 경우 1은 팰린드롬이다. + * S = 5, E = 7인 경우 1, 2, 1은 팰린드롬이다. + * 자연수 N개와 질문 M개가 모두 주어졌을 때, 명우의 대답을 구하는 프로그램을 작성하시오. + * + * ? 입력 + * 첫째 줄에 수열의 크기 N (1 ≤ N ≤ 2,000)이 주어진다. + * 둘째 줄에는 홍준이가 칠판에 적은 수 N개가 순서대로 주어진다. 칠판에 적은 수는 100,000보다 작거나 같은 자연수이다.* + * 셋째 줄에는 홍준이가 한 질문의 개수 M (1 ≤ M ≤ 1,000,000)이 주어진다. + * 넷째 줄부터 M개의 줄에는 홍준이가 명우에게 한 질문 S와 E가 한 줄에 하나씩 주어진다. + * + * 7 -> n + * 1 2 1 3 1 2 1 -> arr[1] ~ arr[n] + * 4 -> t + * 1 3 -> s e + * 2 5 -> s e + * 3 3 -> s e + * 5 7 -> s e + * + * ? 출력 + * 총 M개의 줄에 걸쳐 홍준이의 질문에 대한 명우의 답을 입력으로 주어진 순서에 따라서 출력한다. 팰린드롬인 경우에는 1, 아닌 경우에는 0을 출력한다. + * + * 1 + * 0 + * 1 + * 1 + * + * ? 채점 결과 + * * 시간: 0.888초 + * * 메모리: 316MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.IV; + +import java.io.*; +import java.util.StringTokenizer; + +public class G4_10942 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int[][] dp; + + public static void main(String[] args) throws IOException { + // * 1. 입력 받기 + n = Integer.parseInt(br.readLine()); + + arr = new int[n+1]; + dp = new int[n+1][n+1]; + + st = new StringTokenizer(br.readLine()); + for (int i = 1; i <= n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + + // * 2. DP 테이블 초기화 + Start Case 설정 + for (int i = 1; i <= n; i++) { + dp[i][i] = 1; + } + + // * 3. DP(Tabulation: Bottom-Up) + for (int j = 1; j <= n; j++) { + for (int i = 1; i <= n; i++) { + if (i >= j) { + continue; + } else if (j - i == 1) { + if (arr[i] == arr[j]) { + dp[i][j] = 1; + } + } else { + if (dp[i+1][j-1] == 1 && arr[i] == arr[j]) { + dp[i][j] = 1; + } + } + } + } + + // * 4. 각 테스트 케이스마다 정답 출력 + StringBuffer sb = new StringBuffer(); + int t = Integer.parseInt(br.readLine()); + for (int i = 0; i < t; i++) { + st = new StringTokenizer(br.readLine()); + int s = Integer.parseInt(st.nextToken()); + int e = Integer.parseInt(st.nextToken()); + + sb.append(dp[s][e] + "\n"); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } +} From 920400de3db395b7b64fc370fd2e1675d3496f45 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 15 Sep 2022 09:48:20 +0900 Subject: [PATCH 076/163] =?UTF-8?q?[BOJ-20058-JAVA]=20=EB=A7=88=EB=B2=95?= =?UTF-8?q?=EC=82=AC=20=EC=83=81=EC=96=B4=EC=99=80=20=ED=8C=8C=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=EC=8A=A4=ED=86=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_20058.java | 214 +++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_20058.java diff --git a/java/BOJ/Gold/IV/G4_20058.java b/java/BOJ/Gold/IV/G4_20058.java new file mode 100644 index 0000000..62ddc21 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_20058.java @@ -0,0 +1,214 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/20058 + * + * ? 제목: 마법사 상어와 파이어스톰 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다. 오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 얼음의 양을 의미한다. A[r][c]가 0인 경우 얼음이 없는 것이다. + * 파이어스톰을 시전하려면 시전할 때마다 단계 L을 결정해야 한다. 파이어스톰은 먼저 격자를 2L × 2L 크기의 부분 격자로 나눈다. 그 후, 모든 부분 격자를 시계 방향으로 90도 회전시킨다. 이후 얼음이 있는 칸 3개 또는 그 이상과 인접해있지 않은 칸은 얼음의 양이 1 줄어든다. (r, c)와 인접한 칸은 (r-1, c), (r+1, c), (r, c-1), (r, c+1)이다. 아래 그림의 칸에 적힌 정수는 칸을 구분하기 위해 적은 정수이다. + * 마법을 시전하기 전 L = 1 L = 2 + * 마법사 상어는 파이어스톰을 총 Q번 시전하려고 한다. 모든 파이어스톰을 시전한 후, 다음 2가지를 구해보자. + * 남아있는 얼음 A[r][c]의 합 + * 남아있는 얼음 중 가장 큰 덩어리가 차지하는 칸의 개수 + * 얼음이 있는 칸이 얼음이 있는 칸과 인접해 있으면, 두 칸을 연결되어 있다고 한다. 덩어리는 연결된 칸의 집합이다. + * + * ? 입력 & 파싱 + * 첫째 줄에 N과 Q가 주어진다. 둘째 줄부터 2N개의 줄에는 격자의 각 칸에 있는 얼음의 양이 주어진다. r번째 줄에서 c번째 주어지는 정수는 A[r][c] 이다. + * 마지막 줄에는 마법사 상어가 시전한 단계 L1, L2, ..., LQ가 순서대로 주어진다. + * + * 3 1 -> n q + * 1 2 3 4 5 6 7 8 -> arr[0][0] ~ arr[0][2^n - 1] + * 8 7 6 5 4 3 2 1 + * 1 2 3 4 5 6 7 8 + * 8 7 6 5 4 3 2 1 + * 1 2 3 4 5 6 7 8 + * 8 7 6 5 4 3 2 1 + * 1 2 3 4 5 6 7 8 + * 8 7 6 5 4 3 2 1 -> arr[2^n - 1][0] ~ arr[2^n - 1][2^n - 1] + * 1 -> fire[0] ~ fire[q-1] + * + * ? 출력 + * 첫째 줄에 남아있는 얼음 A[r][c]의 합을 출력하고, 둘째 줄에 가장 큰 덩어리가 차지하는 칸의 개수를 출력한다. 단, 덩어리가 없으면 0을 출력한다.\ + * + * 284 + * 64 + * + * ? 제한 + * 2 ≤ N ≤ 6 + * 1 ≤ Q ≤ 1,000 + * 0 ≤ A[r][c] ≤ 100 + * 0 ≤ Li ≤ N + * + * ? 채점 결과 + * * 시간: 0.316초 + * * 메모리: 54MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.IV; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.StringTokenizer; + +public class G4_20058 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, q, len; + static int[][] arr; + static int[] fire; + + // * 4방 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + // * 초기 설정 + static boolean[][] visited; + static ArrayList mass = new ArrayList<>(); + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + for (int l : fire) { // * 2. 파이어스톰 시도마다 90도 회전 후 얼음 녹이기 + arr = clockwiseRotate((int) Math.pow(2, l)); // * 기준격자마다 회전 + melt(); // * 얼음 녹이기 + } + + int sum = findSum(); // * 3. 남아있는 얼음 개수의 합 + int max = findMax(); // * 4. 남아있는 얼음 덩어리의 개수의 최댓값 + + // * 5. 출력 + bw.write(sum + "\n"); + bw.write(max + "\n"); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + q = Integer.parseInt(st.nextToken()); + len = (int) Math.pow(2, n); + + arr = new int[len][len]; + fire = new int[q]; + + for (int i = 0; i < len; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < len; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < q; i++) { + fire[i] = Integer.parseInt(st.nextToken()); + } + } + + // 기준격자길이(l)를 기준으로 시계방향 90도 회전 + public static int[][] clockwiseRotate(int l) { + int[][] newArr = new int[len][len]; + + for (int x = 0; x < len; x += l) { + for (int y = 0; y < len; y += l) { + for (int i = x; i < x + l; i++) { + for (int j = y; j < y + l; j++) { + newArr[j-y+x][l-1-i+x+y] = arr[i][j]; + } + } + } + } + + return newArr; + } + + // 인접한 4방의 얼음이 있는 경우가 3개 미만일 때 얼음녹이기 + public static void melt() { + ArrayList list = new ArrayList<>(); + + for (int i = 0; i < len; i++) { + for (int j = 0; j < len; j++) { + int count = 0; + for (int k = 0; k < 4; k++) { + int ni = i + dx[k]; + int nj = j + dy[k]; + + if (ni < 0 || nj < 0 || ni >= len || nj >= len) { + continue; + } + + if (arr[ni][nj] > 0) { + count++; + } + } + + if (count < 3) { + list.add(new int[] {i, j}); + } + } + } + + for (int[] m : list) { + if (arr[m[0]][m[1]] > 0) { + arr[m[0]][m[1]]--; + } + } + } + + // 남아있는 얼음 개수 합 구하기 + public static int findSum() { + int sum = 0; + for (int i = 0; i < len; i++) { + for (int j = 0; j < len; j++) { + sum += arr[i][j]; + } + } + return sum; + } + + // 남아있는 얼음 덩어리의 개수 최댓값 구하기 DFS + public static int findMax() { + visited = new boolean[len][len]; + + for (int i = 0; i < len; i++) { + for (int j = 0; j < len; j++) { + if (arr[i][j] != 0 && !visited[i][j]) { + visited[i][j] = true; + mass.add(1); + dfs(i, j); + } + } + } + + return mass.size() != 0 ? Collections.max(mass) : 0; + } + + // DFS + public static void dfs(int x, int y) { + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (nx < 0 || ny < 0 || nx >= len || ny >= len) { + continue; + } + + if (!visited[nx][ny] && arr[nx][ny] > 0) { + mass.set(mass.size()-1, mass.get(mass.size()-1)+1); + visited[nx][ny] = true; + dfs(nx, ny); + } + } + } +} From 2929f7b3a21a516441b857b40204d4f1ea6fa93e Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 16 Sep 2022 16:03:45 +0900 Subject: [PATCH 077/163] =?UTF-8?q?[BOJ-11049-JAVA]=20=ED=96=89=EB=A0=AC?= =?UTF-8?q?=20=EA=B3=B1=EC=85=88=20=EC=88=9C=EC=84=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_11049.java | 107 ++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_11049.java diff --git a/java/BOJ/Gold/III/G3_11049.java b/java/BOJ/Gold/III/G3_11049.java new file mode 100644 index 0000000..b8d4de8 --- /dev/null +++ b/java/BOJ/Gold/III/G3_11049.java @@ -0,0 +1,107 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11049 + * + * ? 제목: 행렬 곱셈 순서 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 크기가 N×M인 행렬 A와 M×K인 B를 곱할 때 필요한 곱셈 연산의 수는 총 N×M×K번이다. 행렬 N개를 곱하는데 필요한 곱셈 연산의 수는 행렬을 곱하는 순서에 따라 달라지게 된다. + * 예를 들어, A의 크기가 5×3이고, B의 크기가 3×2, C의 크기가 2×6인 경우에 행렬의 곱 ABC를 구하는 경우를 생각해보자. + * AB를 먼저 곱하고 C를 곱하는 경우 (AB)C에 필요한 곱셈 연산의 수는 5×3×2 + 5×2×6 = 30 + 60 = 90번이다. + * BC를 먼저 곱하고 A를 곱하는 경우 A(BC)에 필요한 곱셈 연산의 수는 3×2×6 + 5×3×6 = 36 + 90 = 126번이다. + * 같은 곱셈이지만, 곱셈을 하는 순서에 따라서 곱셈 연산의 수가 달라진다. + * 행렬 N개의 크기가 주어졌을 때, 모든 행렬을 곱하는데 필요한 곱셈 연산 횟수의 최솟값을 구하는 프로그램을 작성하시오. 입력으로 주어진 행렬의 순서를 바꾸면 안 된다. + * + * ? 입력 & 파싱 + * 첫째 줄에 행렬의 개수 N(1 ≤ N ≤ 500)이 주어진다. + * 둘째 줄부터 N개 줄에는 행렬의 크기 r과 c가 주어진다. (1 ≤ r, c ≤ 500) + * 항상 순서대로 곱셈을 할 수 있는 크기만 입력으로 주어진다. + * + * 3 -> n + * 5 3 -> r c + * 3 2 -> r c + * 2 6 -> r c + * + * ? 출력 + * 첫째 줄에 입력으로 주어진 행렬을 곱하는데 필요한 곱셈 연산의 최솟값을 출력한다. 정답은 231-1 보다 작거나 같은 자연수이다. 또한, 최악의 순서로 연산해도 연산 횟수가 231-1보다 작거나 같다. + * + * 90 + * + * ? 채점 결과 + * * 시간: 0.208초 + * * 메모리: 14MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G3_11049 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[][] arr; + + // * 초기 설정 + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP Table 초기화 + for (int[] d : dp) { + Arrays.fill(d, Integer.MAX_VALUE); + } + + // * 3. Start Case 설정 + for (int i = 0; i < n; i++) { + dp[i][i] = 0; + } + + for (int i = 0; i < n-1; i++) { + dp[i][i+1] = arr[i][0] * arr[i][1] * arr[i+1][1]; + } + + // * 4. DP(Tabulation: Bottom-Up) + for (int k = 2; k < n; k++) { + for (int i = 0; i < n-2; i++) { + if (i + k >= n) { + continue; + } + + for (int j = i; j < i + k; j++) { + dp[i][i+k] = Math.min( + dp[i][i+k], + dp[i][j] + dp[j+1][i+k] + arr[i][0] * arr[j][1] * arr[i+k][1] + ); + } + } + } + + // * 5. 정답 출력 + System.out.println(dp[0][n-1]); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + dp = new int[n][n]; + + arr = new int[n][2]; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + int r = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + arr[i][0] = r; + arr[i][1] = c; + } + } +} \ No newline at end of file From 5f4aa7ae9e0451984e1cb404b8946c4aafa6f652 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 17 Sep 2022 15:43:19 +0900 Subject: [PATCH 078/163] =?UTF-8?q?[BOJ-16940-JAVA]=20BFS=20=EC=8A=A4?= =?UTF-8?q?=ED=8E=98=EC=85=9C=EC=A0=80=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_16940.java | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_16940.java diff --git a/java/BOJ/Gold/III/G3_16940.java b/java/BOJ/Gold/III/G3_16940.java new file mode 100644 index 0000000..008af76 --- /dev/null +++ b/java/BOJ/Gold/III/G3_16940.java @@ -0,0 +1,122 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16940 + * + * ? 제목: BFS 스페셜저지 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * BOJ에서 정답이 여러가지인 경우에는 스페셜 저지를 사용한다. 스페셜 저지는 유저가 출력한 답을 검증하는 코드를 통해서 정답 유무를 결정하는 방식이다. 오늘은 스페셜 저지 코드를 하나 만들어보려고 한다. + * 정점의 개수가 N이고, 정점에 1부터 N까지 번호가 매겨져있는 양방향 그래프가 있을 때, BFS 알고리즘은 다음과 같은 형태로 이루어져 있다. + * 큐에 시작 정점을 넣는다. 이 문제에서 시작 정점은 1이다. 1을 방문했다고 처리한다. + * 큐가 비어 있지 않은 동안 다음을 반복한다. + * 큐에 들어있는 첫 정점을 큐에서 꺼낸다. 이 정점을 x라고 하자. + * x와 연결되어 있으면, 아직 방문하지 않은 정점 y를 모두 큐에 넣는다. 모든 y를 방문했다고 처리한다. + * 2-2 단계에서 방문하지 않은 정점을 방문하는 순서는 중요하지 않다. 따라서, BFS의 결과는 여러가지가 나올 수 있다. + * 트리가 주어졌을 때, 올바른 BFS 방문 순서인지 구해보자. + * + * ? 입력 & 파싱 + * 첫째 줄에 정점의 수 N(2 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N-1개의 줄에는 트리의 간선 정보가 주어진다. 마지막 줄에는 BFS 방문 순서가 주어진다. BFS 방문 순서는 항상 N개의 정수로 이루어져 있으며, 1부터 N까지 자연수가 한 번씩 등장한다. + * + * 4 -> n + * 1 2 -> a b + * 1 3 -> a b + * 2 4 -> a b + * 1 2 3 4 -> sequence + * + * ? 출력 + * 입력으로 주어진 BFS 방문 순서가 올바른 순서면 1, 아니면 0을 출력한다. + * + * 1 + * + * ? 채점 결과 + * * 시간: 0.808초 + * * 메모리: 75MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; + +public class G3_16940 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, result; + static ArrayList[] arr; + static int[] sequence, order; + + // * 초기 설정 + static boolean[] visited; + + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + bfs(); // * 2. BFS + System.out.println(result); // * 3. 결과 출력 + } + + private static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(1); + visited[1] = true; + + int idx = 0; + while (!queue.isEmpty()) { + int cur = queue.poll(); + + if (sequence[idx++] != cur) { + result = 0; + break; + } + + for (int next : arr[cur]) { + if (!visited[next]) { + visited[next] = true; + queue.add(next); + } + } + } + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + result = 1; + + arr = new ArrayList[n+1]; + order = new int[n+1]; + visited = new boolean[n+1]; + + for (int i = 1; i <= n; i++) { + arr[i] = new ArrayList<>(); + } + + for (int i = 0; i < n-1; i++) { + st = new StringTokenizer(br.readLine()); + + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + arr[a].add(b); + arr[b].add(a); + } + + sequence = new int[n]; + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + sequence[i] = Integer.parseInt(st.nextToken()); + order[sequence[i]] = i; + } + + // ************ 주어진 탐색 순서를 기준으로 인접노드리스트 배열 정렬 ***************** + for (int i = 1; i <= n; i++) { + arr[i].sort((a, b) -> order[a] - order[b]); + } + } +} From e0f7553abc585b0396a37343f5ba23fa3b5fcb95 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sun, 18 Sep 2022 17:38:44 +0900 Subject: [PATCH 079/163] [BOJ-9252-JAVA] LCS2 --- java/BOJ/Gold/IV/G4_9252.java | 89 +++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_9252.java diff --git a/java/BOJ/Gold/IV/G4_9252.java b/java/BOJ/Gold/IV/G4_9252.java new file mode 100644 index 0000000..747a9cb --- /dev/null +++ b/java/BOJ/Gold/IV/G4_9252.java @@ -0,0 +1,89 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/9252 + * + * ? 제목: LCS2 + * ? 시간 제한: 0.1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. + * 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다. + * + * ? 입력 & 파싱 + * 첫째 줄과 둘째 줄에 두 문자열이 주어진다. 문자열은 알파벳 대문자로만 이루어져 있으며, 최대 1000글자로 이루어져 있다. + * + * ACAYKP -> s1 + * CAPCAK -> s2 + * + * ? 출력 + * 첫째 줄에 입력으로 주어진 두 문자열의 LCS의 길이를, 둘째 줄에 LCS를 출력한다. + * LCS가 여러 가지인 경우에는 아무거나 출력하고, LCS의 길이가 0인 경우에는 둘째 줄을 출력하지 않는다. + * + * 4 + * ACAK + * + * ? 채점 결과 + * * 시간: 0.104초 + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.IV; + +import java.io.*; + +public class G4_9252 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + static int n1, n2; + static char[] s1, s2; + static int[][] lcs; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) : LCS + for (int i = 1; i <= n1; i++) { + for (int j = 1; j <= n2; j++) { + if (s1[i-1] == s2[j-1]) { + lcs[i][j] = lcs[i-1][j-1] + 1; + } else { + lcs[i][j] = Math.max(lcs[i-1][j], lcs[i][j-1]); + } + } + } + + // * 3. LCS 문자열 구하기 + StringBuffer sb = new StringBuffer(); + int i = n1, j = n2; + while (i > 0 && j > 0) { + if (lcs[i][j] == lcs[i-1][j]) { + i--; + } else if (lcs[i][j] == lcs[i][j-1]) { + j--; + } else { + sb.append(s1[i-1]); + i--; + j--; + } + } + + // * 4. 정답 출력 + System.out.println(sb.length()); + if (sb.length() != 0) { + System.out.println(sb.reverse().toString()); + } + } + + // 입력 받기 + public static void input() throws IOException { + s1 = br.readLine().toCharArray(); + s2 = br.readLine().toCharArray(); + + n1 = s1.length; + n2 = s2.length; + + lcs = new int[n1+1][n2+1]; + } +} From b499a886bb56b89718c86e36e460593304ea1e25 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 19 Sep 2022 11:54:29 +0900 Subject: [PATCH 080/163] =?UTF-8?q?[BOJ-16724-JAVA]=20=ED=94=BC=EB=A6=AC?= =?UTF-8?q?=20=EB=B6=80=EB=8A=94=20=EC=82=AC=EB=82=98=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_16724.java | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_16724.java diff --git a/java/BOJ/Gold/III/G3_16724.java b/java/BOJ/Gold/III/G3_16724.java new file mode 100644 index 0000000..2424057 --- /dev/null +++ b/java/BOJ/Gold/III/G3_16724.java @@ -0,0 +1,122 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16724 + * + * ? 제목: 피리 부는 사나이 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 피리 부는 사나이 성우는 오늘도 피리를 분다. + * 성우가 피리를 불 때면 영과일 회원들은 자기도 모르게 성우가 정해놓은 방향대로 움직이기 시작한다. 성우가 정해놓은 방향은 총 4가지로 U, D, L, R이고 각각 위, 아래, 왼쪽, 오른쪽으로 이동하게 한다. + * 이를 지켜보던 재훈이는 더 이상 움직이기 힘들어하는 영과일 회원들을 지키기 위해 특정 지점에 ‘SAFE ZONE’ 이라는 최첨단 방음 시설을 만들어 회원들이 성우의 피리 소리를 듣지 못하게 하려고 한다. 하지만 예산이 넉넉하지 않은 재훈이는 성우가 설정해 놓은 방향을 분석해서 최소 개수의 ‘SAFE ZONE’을 만들려 한다. + * 성우가 설정한 방향 지도가 주어졌을 때 재훈이를 도와서 영과일 회원들이 지도 어느 구역에 있더라도 성우가 피리를 불 때 ‘SAFE ZONE’에 들어갈 수 있게 하는 ‘SAFE ZONE’의 최소 개수를 출력하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫 번째 줄에 지도의 행의 수를 나타내는 N(1 ≤ N ≤ 1,000)과 지도의 열의 수를 나타내는 M(1 ≤ M ≤ 1,000)이 주어진다. + * 두 번째 줄부터 N개의 줄에 지도의 정보를 나타내는 길이가 M인 문자열이 주어진다. + * 지도 밖으로 나가는 방향의 입력은 주어지지 않는다. + * + * 3 4 -> n m + * DLLL -> arr[0][0] ~ arr[0][m-1] + * DRLU + * RRRU -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 첫 번째 줄에 ‘SAFE ZONE’의 최소 개수를 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 0.312초 + * * 메모리: 28MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.III; + +import java.io.*; +import java.util.HashMap; +import java.util.StringTokenizer; + +public class G3_16724 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static char[][] arr; + + // * 초기 설정 + static int count = 0; + static boolean[][] visited; + static int[][] route; + + // * 4방(DULR) + static HashMap dir = new HashMap<>(); + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 방문하지 않은 위치에서 DFS수행 + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (!visited[i][j]) { + visited[i][j] = true; + dfs(i, j); + } + } + } + + // * 3. 독립된 경로의 개수 출력 + System.out.println(count); + } + + // DFS + public static int dfs(int x, int y) { + if (route[x][y] > 0) { + return route[x][y]; + } + + int nx = x + dir.get(arr[x][y])[0]; + int ny = y + dir.get(arr[x][y])[1]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + return ++count; + } + + // 방문했던 곳일 때 + if (visited[nx][ny]) { + // 현재 DFS 경로 상에서 싸이클이 발생한 경우 + if (route[nx][ny] == 0) { + route[x][y] = ++count; // 독립된 경로의 개수 + 1 + } else { // 이미 찾았던 경로인 경우 + route[x][y] = route[nx][ny]; // 해당 경로에 포함 + } + return route[x][y]; + } + + visited[nx][ny] = true; + route[x][y] = dfs(nx, ny); + return route[x][y]; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new char[n][m]; + route = new int[n][m]; + visited = new boolean[n][m]; + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + + dir.put('D', new int[] {1, 0}); + dir.put('U', new int[] {-1, 0}); + dir.put('R', new int[] {0, 1}); + dir.put('L', new int[] {0, -1}); + } +} From 23bfbbf05e0822934dfb44711628bf36da36263e Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 20 Sep 2022 11:11:57 +0900 Subject: [PATCH 081/163] =?UTF-8?q?[BOJ-1915-JAVA]=20=EA=B0=80=EC=9E=A5=20?= =?UTF-8?q?=ED=81=B0=20=EC=A0=95=EC=82=AC=EA=B0=81=ED=98=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_1915.java | 99 +++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_1915.java diff --git a/java/BOJ/Gold/IV/G4_1915.java b/java/BOJ/Gold/IV/G4_1915.java new file mode 100644 index 0000000..f06a0da --- /dev/null +++ b/java/BOJ/Gold/IV/G4_1915.java @@ -0,0 +1,99 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1915 + * + * ? 제목: 가장 큰 정사각형 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * n×m의 0, 1로 된 배열이 있다. 이 배열에서 1로 된 가장 큰 정사각형의 크기를 구하는 프로그램을 작성하시오. + * 0 1 0 0 + * 0 1 1 1 + * 1 1 1 0 + * 0 0 1 0 + * 위와 같은 예제에서는 가운데의 2×2 배열이 가장 큰 정사각형이다. + * + * ? 입력 & 파싱 + * 첫째 줄에 n, m(1 ≤ n, m ≤ 1,000)이 주어진다. 다음 n개의 줄에는 m개의 숫자로 배열이 주어진다. + * + * 4 4 -> n m + * 0100 -> arr[0][0] ~ arr[0][m-1] + * 0111 + * 1110 + * 0010 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 첫째 줄에 가장 큰 정사각형의 넓이를 출력한다. + * + * 4 + * + * ? 채점 결과 + * * 시간: 0.236초 + * * 메모리: 25MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.IV; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G4_1915 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static char[][] arr; + + // * 초기 설정 + static int max = 0; + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP Table 초기화 + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + dp[i][j] = arr[i][j] - '0'; + } + } + + // * 3. DP(Tabulation: Bottom-Up) + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (i == 0 || j == 0) { + max = Math.max(max, arr[i][j] - '0'); + continue; + } + + if (arr[i][j] == '0') { + continue; + } + dp[i][j] = Math.min(dp[i-1][j-1], Math.min(dp[i-1][j], dp[i][j-1])) + 1; + max = Math.max(dp[i][j], max); + } + } + + // * 4. 출력 + System.out.println(max * max); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new char[n][m]; + dp = new int[n][m]; + + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } +} From 76dfa93a23041ce521ecfdac5f8b19fff8bda973 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 21 Sep 2022 16:26:29 +0900 Subject: [PATCH 082/163] =?UTF-8?q?[BOJ-5972-JAVA]=20=ED=83=9D=EB=B0=B0=20?= =?UTF-8?q?=EB=B0=B0=EC=86=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_5972.java | 123 +++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_5972.java diff --git a/java/BOJ/Gold/V/G5_5972.java b/java/BOJ/Gold/V/G5_5972.java new file mode 100644 index 0000000..51579d1 --- /dev/null +++ b/java/BOJ/Gold/V/G5_5972.java @@ -0,0 +1,123 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/5972 + * + * ? 택배 배송 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 농부 현서는 농부 찬홍이에게 택배를 배달해줘야 합니다. 그리고 지금, 갈 준비를 하고 있습니다. 평화롭게 가려면 가는 길에 만나는 모든 소들에게 맛있는 여물을 줘야 합니다. 물론 현서는 구두쇠라서 최소한의 소들을 만나면서 지나가고 싶습니다. + * 농부 현서에게는 지도가 있습니다. N (1 <= N <= 50,000) 개의 헛간과, 소들의 길인 M (1 <= M <= 50,000) 개의 양방향 길이 그려져 있고, 각각의 길은 C_i (0 <= C_i <= 1,000) 마리의 소가 있습니다. 소들의 길은 두 개의 떨어진 헛간인 A_i 와 B_i (1 <= A_i <= N; 1 <= B_i <= N; A_i != B_i)를 잇습니다. 두 개의 헛간은 하나 이상의 길로 연결되어 있을 수도 있습니다. 농부 현서는 헛간 1에 있고 농부 찬홍이는 헛간 N에 있습니다. + * 다음 지도를 참고하세요. + * + * [2]--- + * / | \ + * /1 | \ 6 + * / | \ + * [1] 0| --[3] + * \ | / \2 + * 4\ | /4 [6] + * \ | / /1 + * [4]-----[5] + * 3 + * 농부 현서가 선택할 수 있는 최선의 통로는 1 -> 2 -> 4 -> 5 -> 6 입니다. 왜냐하면 여물의 총합이 1 + 0 + 3 + 1 = 5 이기 때문입니다. + * 농부 현서의 지도가 주어지고, 지나가는 길에 소를 만나면 줘야할 여물의 비용이 주어질 때 최소 여물은 얼마일까요? 농부 현서는 가는 길의 길이는 고려하지 않습니다. + * + * ? 입력 & 파싱 + * 첫째 줄에 N과 M이 공백을 사이에 두고 주어집니다. + * 둘째 줄부터 M+1번째 줄까지 세 개의 정수 A_i, B_i, C_i가 주어집니다. + * + * 6 8 -> n m + * 4 5 3 -> a b c + * 2 4 0 -> a b c + * 4 1 4 -> a b c + * 2 1 1 -> a b c + * 5 6 1 -> a b c + * 3 6 2 -> a b c + * 3 2 6 -> a b c + * 3 4 4 -> a b c + * + * ? 출력 + * 첫째 줄에 농부 현서가 가져가야 될 최소 여물을 출력합니다. + * + * 5 + * + * ? 채점 결과 + * * 시간: 0.568초 + * * 메모리: 44MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +public class G5_5972 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static ArrayList[] arr; + + // * 초기 설정 + static final long max = 25_000_000_000L; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 다익스트라 알고리즘 + long[] visited = new long[n+1]; + Arrays.fill(visited, max); + PriorityQueue pq = new PriorityQueue<>((a, b) -> Long.compare(a[1], b[1])); + pq.add(new long[] {1, 0}); + visited[1] = 0; + + while (!pq.isEmpty()) { + long[] cur = pq.poll(); + + if (visited[(int) cur[0]] < cur[1]) { + continue; + } + + for (long[] next : arr[(int) cur[0]]) { + if (visited[(int) next[0]] > next[1] + cur[1]) { + visited[(int) next[0]] = next[1] + cur[1]; + pq.add(new long[] {next[0], visited[(int) next[0]]}); + } + } + } + + // * 3. 정답 출력 + System.out.println(visited[n]); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new ArrayList[n+1]; + + for (int i = 1; i <= n; i++) { + arr[i] = new ArrayList<>(); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + arr[a].add(new long[] {b, c}); + arr[b].add(new long[] {a, c}); + } + + } +} From 7bdb2d5240d0e4bcae368132d09d0e1a279c37c0 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 22 Sep 2022 11:22:43 +0900 Subject: [PATCH 083/163] =?UTF-8?q?[BOJ-1965-JAVA]=20=EC=83=81=EC=9E=90?= =?UTF-8?q?=EB=84=A3=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/II/S2_1965.java | 94 +++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 java/BOJ/Silver/II/S2_1965.java diff --git a/java/BOJ/Silver/II/S2_1965.java b/java/BOJ/Silver/II/S2_1965.java new file mode 100644 index 0000000..fa5d649 --- /dev/null +++ b/java/BOJ/Silver/II/S2_1965.java @@ -0,0 +1,94 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1965 + * + * ? 상자넣기 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 정육면체 모양의 상자가 일렬로 늘어서 있다. 상자마다 크기가 주어져 있는데, 앞에 있는 상자의 크기가 뒤에 있는 상자의 크기보다 작으면, 앞에 있는 상자를 뒤에 있는 상자 안에 넣을 수가 있다. 예를 들어 앞에서부터 순서대로 크기가 (1, 5, 2, 3, 7)인 5개의 상자가 있다면, 크기 1인 상자를 크기 5인 상자에 넣고, 다시 이 상자를 크기 7인 상자 안에 넣을 수 있다. 하지만 이렇게 상자를 넣을 수 있는 방법은 여러 가지가 있을 수 있다. 앞의 예에서 차례대로 크기가 1, 2, 3, 7인 상자를 선택하면 총 4개의 상자가 한 개의 상자에 들어가게 된다. + * 상자의 크기가 주어질 때, 한 번에 넣을 수 있는 최대의 상자 개수를 출력하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 파일의 첫 번째 줄은 상자의 개수 n (1 ≤ n ≤ 1000)을 나타낸다. 두 번째 줄에는 각 상자의 크기가 순서대로 주어진다. 상자의 크기는 1,000을 넘지 않는 자연수이다. + * + * 8 + * 1 6 2 5 7 3 5 6 + * + * ? 출력 + * + * 5 + * + * ? 채점 결과 + * * 시간: 0.08초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.II; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class S2_1965 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 & 초기 설정 + static int n; + static int[] arr, dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. Start Case 설정 + dp[0] = arr[0]; + int p = 1; + + // * 3. LIS(DP: Tabulation) + for (int i = 0; i < n; i++) { + if (dp[p-1] < arr[i]) { + dp[p++] = arr[i]; + } else { + int left = 0; + int right = p-1; + + while (left <= right) { + int mid = (left + right) / 2; + + if (dp[mid] == arr[i]) { + left = mid; + break; + } + + if (dp[mid] > arr[i]) { + right = mid-1; + } else { + left = mid+1; + } + } + + dp[left] = arr[i]; + } + } + + // * 4. 정답 출력 + System.out.println(p); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n]; + dp = new int[n]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + } +} From dbca86d0772b47bfd71627ab0a16e89e7d44bf09 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 22 Sep 2022 11:39:08 +0900 Subject: [PATCH 084/163] =?UTF-8?q?[BOJ-15988-JAVA]=201,=202,=203=20?= =?UTF-8?q?=EB=8D=94=ED=95=98=EA=B8=B0=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/II/S2_15988.java | 80 ++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 java/BOJ/Silver/II/S2_15988.java diff --git a/java/BOJ/Silver/II/S2_15988.java b/java/BOJ/Silver/II/S2_15988.java new file mode 100644 index 0000000..6b3fcc2 --- /dev/null +++ b/java/BOJ/Silver/II/S2_15988.java @@ -0,0 +1,80 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/15988 + * + * ? 제목: 1, 2, 3 더하기 3 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 7가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다. + * 1+1+1+1 + * 1+1+2 + * 1+2+1 + * 2+1+1 + * 2+2 + * 1+3 + * 3+1 + * 정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오. + * + * ? 입력 + * 첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 1,000,000보다 작거나 같다. + * + * 3 -> t + * 4 -> num + * 7 -> num + * 10 -> num + * + * ? 출력 + * 각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다. + * + * 7 + * 44 + * 274 + * + * ? 채점 결과 + * * 시간: 0.124초 + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Silver.II; + +import java.io.*; + +public class S2_15988 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + public static void main(String[] args) throws IOException { + // * 초기 설정 + int[] dp = new int[1_000_001]; + StringBuffer sb = new StringBuffer(); + int div = 1_000_000_009; + + // * Start Case + dp[0] = 0; + dp[1] = 1; + dp[2] = 2; + dp[3] = 4; + + // * 1. DP(Tabulation: Bottom-Up) + for (int i = 4; i < dp.length; i++) { + dp[i] = ((dp[i-1] % div + dp[i-2] % div) % div + dp[i-3] % div) % div; + } + + // * 2. 입력 받기 + int t = Integer.parseInt(br.readLine()); + for (int i = 0; i < t; i++) { + int num = Integer.parseInt(br.readLine()); + sb.append(dp[num] + "\n"); + } + + // * 3. 출력 + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } +} From 858193d3f2bb9c0160ae832668240f7e74fd7069 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 23 Sep 2022 14:25:37 +0900 Subject: [PATCH 085/163] =?UTF-8?q?[BOJ-14267-JAVA]=20=ED=9A=8C=EC=82=AC?= =?UTF-8?q?=20=EB=AC=B8=ED=99=941?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_14267.java | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_14267.java diff --git a/java/BOJ/Gold/IV/G4_14267.java b/java/BOJ/Gold/IV/G4_14267.java new file mode 100644 index 0000000..140933c --- /dev/null +++ b/java/BOJ/Gold/IV/G4_14267.java @@ -0,0 +1,97 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14267 + * + * ? 제목: 회사 문화 1 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 영선회사에는 매우 좋은 문화가 있는데, 바로 상사가 직속 부하를 칭찬하면 그 부하가 부하의 직속 부하를 연쇄적으로 칭찬하는 내리 칭찬이 있다. 즉, 상사가 한 직속 부하를 칭찬하면 그 부하의 모든 부하들이 칭찬을 받는다. + * 모든 칭찬에는 칭찬의 정도를 의미하는 수치가 있는데, 이 수치 또한 부하들에게 똑같이 칭찬 받는다. + * 직속 상사와 직속 부하관계에 대해 주어지고, 칭찬에 대한 정보가 주어질 때, 각자 얼마의 칭찬을 받았는지 출력하시오, + * + * ? 입력 & 파싱 + * 첫째 줄에는 회사의 직원 수 n명, 최초의 칭찬의 횟수 m이 주어진다. 직원은 1번부터 n번까지 번호가 매겨져 있다. (2 ≤ n, m ≤ 100,000) + * 둘째 줄에는 직원 n명의 직속 상사의 번호가 주어진다. 직속 상사의 번호는 자신의 번호보다 작으며, 최종적으로 1번이 사장이다. 1번의 경우, 상사가 없으므로 -1이 입력된다. + * 다음 m줄에는 직속 상사로부터 칭찬을 받은 직원 번호 i, 칭찬의 수치 w가 주어진다. (2 ≤ i ≤ n, 1 ≤ w ≤ 1,000) + * 사장은 상사가 없으므로 칭찬을 받지 않는다. + * + * 5 3 -> n m + * -1 1 2 3 4 -> arr[1] ~ arr[n] + * 2 2 -> sub p + * 3 4 -> sub p + * 5 6 -> sub p + * + * ? 출력 + * 1번부터 n번의 직원까지 칭찬을 받은 정도를 출력하시오. + * + * 0 2 6 6 12 + * + * ? 채점 결과 + * * 시간: 0.54초 + * * 메모리: 65MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.IV; + +import java.io.*; +import java.util.*; + +public class G4_14267 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[] arr; + + // * 초기 설정 + static int[] point; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int sub = Integer.parseInt(st.nextToken()); + int p = Integer.parseInt(st.nextToken()); + point[sub] += p; // 시작 포인트 활성화 + } + + // * 2. DP(Tabulation: Bottom-Up) + for (int i = 2; i <= n; i++) { + point[i] += point[arr[i]]; + } + + // * 3. 출력 + StringBuffer sb = new StringBuffer(); + for (int i = 1; i <= n; i++) { + sb.append(point[i] + " "); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n+1]; + point = new int[n+1]; + + st = new StringTokenizer(br.readLine()); + for (int i = 1; i <= n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + } + +} From 5cf938d6f3fc765085f3d44dd0f077675548ce6e Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 24 Sep 2022 23:07:36 +0900 Subject: [PATCH 086/163] =?UTF-8?q?[BOJ-1058-JAVA]=20=EC=B9=9C=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/II/S2_1058.java | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 java/BOJ/Silver/II/S2_1058.java diff --git a/java/BOJ/Silver/II/S2_1058.java b/java/BOJ/Silver/II/S2_1058.java new file mode 100644 index 0000000..c0a8281 --- /dev/null +++ b/java/BOJ/Silver/II/S2_1058.java @@ -0,0 +1,99 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1058 + * + * ? 제목: 친구 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 지민이는 세계에서 가장 유명한 사람이 누구인지 궁금해졌다. 가장 유명한 사람을 구하는 방법은 각 사람의 2-친구를 구하면 된다. 어떤 사람 A가 또다른 사람 B의 2-친구가 되기 위해선, 두 사람이 친구이거나, A와 친구이고, B와 친구인 C가 존재해야 된다. 여기서 가장 유명한 사람은 2-친구의 수가 가장 많은 사람이다. 가장 유명한 사람의 2-친구의 수를 출력하는 프로그램을 작성하시오. + * A와 B가 친구면, B와 A도 친구이고, A와 A는 친구가 아니다. + * + * ? 입력 + * 첫째 줄에 사람의 수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 각 사람이 친구이면 Y, 아니면 N이 주어진다. + * + * 3 -> n + * NYY -> N : 0, Y : 1 로 치환 대입, arr[0][0] ~ arr[0][n-1] + * YNY + * YYN -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 첫째 줄에 가장 유명한 사람의 2-친구의 수를 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 0.084초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.II; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.Queue; + +public class S2_1058 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static int n; + static int[][] arr; + + // * 초기 설정 + static int max = 0; + static boolean[] visited; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. BFS + for (int i = 0; i < n; i++) { + visited = new boolean[n]; + Queue queue = new LinkedList<>(); + queue.add(new int[] {i, 0}); + visited[i] = true; + int count = 0; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[1] == 2) { + break; + } + + for (int j = 0; j < n; j++) { + if (arr[cur[0]][j] == 1 && !visited[j]) { + visited[j] = true; + queue.add(new int[] {j, cur[1] + 1}); + count++; + } + } + } + + if (count > max) { + max = count; + } + } + + // * 3. 출력 + System.out.println(max); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new int[n][n]; + + for (int i = 0; i < n; i++) { + char[] c = br.readLine().toCharArray(); + for (int j = 0; j < n; j++) { + arr[i][j] = (c[j] == 'Y') ? 1 : 0; + } + } + } +} From 90a5300015daa11d2f7aeee630391c798ba45f24 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 25 Sep 2022 13:49:30 +0900 Subject: [PATCH 087/163] =?UTF-8?q?[BOJ-2011-JAVA]=20=EC=95=94=ED=98=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2011.java | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2011.java diff --git a/java/BOJ/Gold/V/G5_2011.java b/java/BOJ/Gold/V/G5_2011.java new file mode 100644 index 0000000..132ce2b --- /dev/null +++ b/java/BOJ/Gold/V/G5_2011.java @@ -0,0 +1,103 @@ +/** + * ? 문제 출처: 백준 온라인 져지 + * ? https://www.acmicpc.net/problem/2011 + * + * ? 제목: 암호 코드 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 상근이와 선영이가 다른 사람들이 남매간의 대화를 듣는 것을 방지하기 위해서 대화를 서로 암호화 하기로 했다. 그래서 다음과 같은 대화를 했다. + * + * 상근: 그냥 간단히 암호화 하자. A를 1이라고 하고, B는 2로, 그리고 Z는 26으로 하는거야. + * 선영: 그럼 안돼. 만약, "BEAN"을 암호화하면 25114가 나오는데, 이걸 다시 글자로 바꾸는 방법은 여러 가지가 있어. + * 상근: 그렇네. 25114를 다시 영어로 바꾸면, "BEAAD", "YAAD", "YAN", "YKD", "BEKD", "BEAN" 총 6가지가 나오는데, BEAN이 맞는 단어라는건 쉽게 알수 있잖아? + * 선영: 예가 적절하지 않았네 ㅠㅠ 만약 내가 500자리 글자를 암호화 했다고 해봐. 그 때는 나올 수 있는 해석이 정말 많은데, 그걸 언제 다해봐? + * 상근: 얼마나 많은데? + * 선영: 구해보자! + * 어떤 암호가 주어졌을 때, 그 암호의 해석이 몇 가지가 나올 수 있는지 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 5000자리 이하의 암호가 주어진다. 암호는 숫자로 이루어져 있다. + * + * 25114 -> str + * + * ? 출력 + * 나올 수 있는 해석의 가짓수를 구하시오. 정답이 매우 클 수 있으므로, 1000000으로 나눈 나머지를 출력한다. + * 암호가 잘못되어 암호를 해석할 수 없는 경우에는 0을 출력한다. + * + * 6 + * + * ? 채점 결과 + * * 시간: 0.076초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class G5_2011 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static void main(String[] args) throws IOException { + // * 파싱(입력받기) + String str = br.readLine(); + + // * 초기 설정 + int len = str.length(); + int div = 1000000; + boolean isError = false; + + // * DP 테이블 초기화 + int[] arr = new int[len+1]; + int[] dp = new int[len+1]; + + // * 예외 처리 + if (str.length() == 0) { + isError = true; + } + else if (str.charAt(0) == '0') { + isError = true; + } + + // * DP (Tabulation: Bottom-Up) + else { + for (int i = 1; i <= len; i++) { + arr[i] = str.charAt(i-1) - '0'; + } + + // * Start Case + dp[0] = 1; + dp[1] = 1; + + for (int i = 2; i <= len; i++) { + int num = arr[i-1] * 10 + arr[i]; + if (arr[i] == 0) { // 0인 곳은 앞자리와 같이 암호가 되어야만 함 + if (!isOk(num)) { // 앞자리와 합친 값이 invalid 할 때 + isError = true; + break; + } else { + dp[i] = dp[i-2]; + } + } else { + if (isOk(num) && arr[i-1] != 0) { // 앞자리와 합친 값이 정상적일 때 + dp[i] = (dp[i-1] % div + dp[i-2] % div) % div; + } else { // 앞자리와 합칠 수 없을 때 + dp[i] = dp[i-1]; + } + } + } + } + + // * 출력 + System.out.println(isError ? 0 : dp[len]); + } + + public static boolean isOk(int num) { + return num >= 1 && num <= 26; + } +} From cdf660f473aed640f3d7789b56618ed8a931db1c Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Mon, 26 Sep 2022 16:24:26 +0900 Subject: [PATCH 088/163] =?UTF-8?q?[BOJ-4803-JAVA]=20=ED=8A=B8=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_4803.java | 158 ++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_4803.java diff --git a/java/BOJ/Gold/IV/G4_4803.java b/java/BOJ/Gold/IV/G4_4803.java new file mode 100644 index 0000000..c8700c8 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_4803.java @@ -0,0 +1,158 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/4803 + * + * ? 제목: 트리 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 그래프는 정점과 간선으로 이루어져 있다. 두 정점 사이에 경로가 있다면, 두 정점은 연결되어 있다고 한다. 연결 요소는 모든 정점이 서로 연결되어 있는 정점의 부분집합이다. 그래프는 하나 또는 그 이상의 연결 요소로 이루어져 있다. + * 트리는 사이클이 없는 연결 요소이다. 트리에는 여러 성질이 있다. 예를 들어, 트리는 정점이 n개, 간선이 n-1개 있다. 또, 임의의 두 정점에 대해서 경로가 유일하다. + * 그래프가 주어졌을 때, 트리의 개수를 세는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 n ≤ 500과 m ≤ n(n-1)/2을 만족하는 정점의 개수 n과 간선의 개수 m이 주어진다. 다음 m개의 줄에는 간선을 나타내는 두 개의 정수가 주어진다. 같은 간선은 여러 번 주어지지 않는다. 정점은 1번부터 n번까지 번호가 매겨져 있다. 입력의 마지막 줄에는 0이 두 개 주어진다. + * + * 6 3 -> n m + * 1 2 -> a b + * 2 3 -> a b + * 3 4 -> a b + * 6 5 -> n m + * 1 2 -> a b + * 2 3 -> a b + * 3 4 -> a b + * 4 5 -> a b + * 5 6 -> a b + * 6 6 -> n m + * 1 2 -> a b + * 2 3 -> a b + * 1 3 -> a b + * 4 5 -> a b + * 5 6 -> a b + * 6 4 -> a b + * 0 0 -> a b + * + * ? 출력 + * 입력으로 주어진 그래프에 트리가 없다면 "No trees."를, 한 개라면 "There is one tree."를, T개(T > 1)라면 "A forest of T trees."를 테스트 케이스 번호와 함께 출력한다. + * + * Case 1: A forest of 3 trees. + * Case 2: There is one tree. + * Case 3: No trees. + * + * ? 채점 결과 + * * 시간: 0.636초 + * * 메모리: 72MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G4_4803 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static ArrayList[] arr; + + // * 초기 설정 + static int[] parent; + + public static void main(String[] args) throws IOException { + StringBuffer sb = new StringBuffer(); + int t = 0; + while (true) { // * 각 테스트 케이스마다 + t++; + input(); // * 1. 입력 받기 + + if (n == 0 && m == 0) { // * 종료 케이스 + break; + } + + parent = IntStream.range(0, n+1).toArray(); // 방문리스트 겸 부모노드 + + // *** 인접 노드 리스트 배열 생성 & 초기화 & 셋팅 + arr = new ArrayList[n+1]; + for (int i = 1; i <= n; i++) { + arr[i] = new ArrayList<>(); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + arr[a].add(b); + arr[b].add(a); + } + + // * 2. BFS: 트리의 갯수 세기 + int count = 0; + for (int i = 1; i <= n; i++) { + if (parent[i] == i) { + boolean hasCycle = false; // * 사이클이 발생하는지 여부 + Queue queue = new LinkedList<>(); + queue.add(new int[] {i, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + for (int next : arr[cur[0]]) { + // * 바로 직전에서 온 노드 제외 + if (next == cur[1]) { + continue; + } + + if (parent[next] == i) { + hasCycle = true; + } else { + parent[next] = i; + queue.add(new int[] {next, cur[0]}); + } + } + } + + // 사이클이 발생하지 않았을 경우에만 count 증가 + if (!hasCycle) { + count++; + } + } + } + + // * 3. 출력값 추가 + switch (count) { + case 0: + sb.append("Case " + t + ": " + "No trees.\n"); + break; + case 1: + sb.append("Case " + t + ": " + "There is one tree.\n"); + break; + default: + sb.append("Case " + t + ": " + "A forest of " + count + " trees.\n"); + break; + } + } + + // * 4. 출력 + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + } +} From e60b17dd4ecc3ff84e783cd75c7327f428e59867 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 27 Sep 2022 19:21:15 +0900 Subject: [PATCH 089/163] [BOJ-1958-JAVA] LCS 3 --- java/BOJ/Gold/III/G3_1958.java | 91 ++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_1958.java diff --git a/java/BOJ/Gold/III/G3_1958.java b/java/BOJ/Gold/III/G3_1958.java new file mode 100644 index 0000000..1123636 --- /dev/null +++ b/java/BOJ/Gold/III/G3_1958.java @@ -0,0 +1,91 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1958 + * + * ? 제목: LCS 3 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 문자열과 놀기를 세상에서 제일 좋아하는 영식이는 오늘도 문자열 2개의 LCS(Longest Common Subsequence)를 구하고 있었다. 어느 날 영식이는 조교들이 문자열 3개의 LCS를 구하는 것을 보았다. 영식이도 도전해 보았지만 실패하고 말았다. + * 이제 우리가 할 일은 다음과 같다. 영식이를 도와서 문자열 3개의 LCS를 구하는 프로그램을 작성하라. + * + * ? 입력 + * 첫 줄에는 첫 번째 문자열이, 둘째 줄에는 두 번째 문자열이, 셋째 줄에는 세 번째 문자열이 주어진다. 각 문자열은 알파벳 소문자로 이루어져 있고, 길이는 100보다 작거나 같다. + * + * abcdefghijklmn -> str1 + * bdefg -> str2 + * efg -> str3 + * + * ? 출력 + * 첫 줄에 첫 번째 문자열과 두 번째 문자열과 세 번째 문자열의 LCS의 길이를 출력한다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 0.116초 + * * 메모리: 17MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class G3_1958 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static String str1, str2, str3; + + // * 초기 설정 + static char[] arr1, arr2, arr3; + static int[][][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) + for (int i = 1; i <= str1.length(); i++) { + for (int j = 1; j <= str2.length(); j++) { + for (int k = 1; k <= str3.length(); k++) { + if (arr1[i] == arr2[j] && arr2[j] == arr3[k]) { + dp[i][j][k] = dp[i-1][j-1][k-1] + 1; + } else { + dp[i][j][k] = Math.max(dp[i-1][j][k], Math.max(dp[i][j-1][k], dp[i][j][k-1])); + } + } + } + } + + // * 3. 출력 + System.out.println(dp[str1.length()][str2.length()][str3.length()]); + } + + public static void input() throws IOException { + str1 = br.readLine(); + str2 = br.readLine(); + str3 = br.readLine(); + + arr1 = new char[str1.length()+1]; + arr2 = new char[str2.length()+1]; + arr3 = new char[str3.length()+1]; + + dp = new int[arr1.length][arr2.length][arr3.length]; + + for (int i = 0; i < str1.length(); i++) { + arr1[i+1] = str1.charAt(i); + } + + for (int i = 0; i < str2.length(); i++) { + arr2[i+1] = str2.charAt(i); + } + + for (int i = 0; i < str3.length(); i++) { + arr3[i+1] = str3.charAt(i); + } + + } +} From 9a3962caf1b450316ec9568d271a1538b83c5f5d Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 28 Sep 2022 18:39:56 +0900 Subject: [PATCH 090/163] =?UTF-8?q?[BOJ-12869-JAVA]=20=EB=AE=A4=ED=83=88?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_12869.java | 146 +++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_12869.java diff --git a/java/BOJ/Gold/IV/G4_12869.java b/java/BOJ/Gold/IV/G4_12869.java new file mode 100644 index 0000000..ad74844 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_12869.java @@ -0,0 +1,146 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/12869 + * + * ? 제목: 뮤탈리스크 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 수빈이는 강호와 함께 스타크래프트 게임을 하고 있다. 수빈이는 뮤탈리스크 1개가 남아있고, 강호는 SCV N개가 남아있다. + * 각각의 SCV는 남아있는 체력이 주어져있으며, 뮤탈리스크를 공격할 수는 없다. 즉, 이 게임은 수빈이가 이겼다는 것이다. + * 뮤탈리스크가 공격을 할 때, 한 번에 세 개의 SCV를 공격할 수 있다. + * + * 첫 번째로 공격받는 SCV는 체력 9를 잃는다. + * 두 번째로 공격받는 SCV는 체력 3을 잃는다. + * 세 번째로 공격받는 SCV는 체력 1을 잃는다. + * + * SCV의 체력이 0 또는 그 이하가 되어버리면, SCV는 그 즉시 파괴된다. 한 번의 공격에서 같은 SCV를 여러 번 공격할 수는 없다. + * 남아있는 SCV의 체력이 주어졌을 때, 모든 SCV를 파괴하기 위해 공격해야 하는 횟수의 최솟값을 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 SCV의 수 N (1 ≤ N ≤ 3)이 주어진다. 둘째 줄에는 SCV N개의 체력이 주어진다. 체력은 60보다 작거나 같은 자연수이다. + * + * 3 -> n + * 12 10 4 -> arr[0] arr[1] arr[2] + * + * ? 출력 + * 첫째 줄에 모든 SCV를 파괴하기 위한 공격 횟수의 최솟값을 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 0.088초 + * * 메모리: 12MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +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 G4_12869 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, answer; + static int[] arr; + + // * 뮤탈리스크 공격 순서 경우 + static int[] dx = {9, 3, 1, 9, 3, 1}; + static int[] dy = {3, 9, 3, 1, 1, 9}; + static int[] dz = {1, 1, 9, 3, 9, 3}; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2-1. n = 1일 때 + if (n == 1) { + answer = arr[0] % 9 == 0 ? arr[0] / 9 : arr[0] / 9 + 1; + } + + // * 2-2. n = 2일 때: BFS + else if (n == 2) { + int[][] dp = new int[61][61]; + dp[arr[0]][arr[1]] = 1; + + Queue queue = new LinkedList<>(); + queue.add(new int[] {arr[0], arr[1]}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == 0 && cur[1] == 0) { + answer = dp[0][0] - 1; + } + + for (int i = 0; i < 2; i++) { + int nx = cur[0] - dx[i]; + int ny = cur[1] - dy[i]; + + nx = Math.max(nx, 0); + ny = Math.max(ny, 0); + + if (dp[nx][ny] == 0) { + dp[nx][ny] = dp[cur[0]][cur[1]] + 1; + queue.add(new int[] {nx, ny}); + } + + } + } + } + + // * 2-3. n = 3일 때: BFS + else { + int[][][] dp = new int[61][61][61]; + dp[arr[0]][arr[1]][arr[2]] = 1; + + Queue queue = new LinkedList<>(); + queue.add(new int[] {arr[0], arr[1], arr[2]}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == 0 && cur[1] == 0 && cur[2] == 0) { + answer = dp[0][0][0] - 1; + } + + for (int i = 0; i < 6; i++) { + int nx = cur[0] - dx[i]; + int ny = cur[1] - dy[i]; + int nz = cur[2] - dz[i]; + + nx = Math.max(nx, 0); + ny = Math.max(ny, 0); + nz = Math.max(nz, 0); + + if (dp[nx][ny][nz] == 0) { + dp[nx][ny][nz] = dp[cur[0]][cur[1]][cur[2]] + 1; + queue.add(new int[] {nx, ny, nz}); + } + } + } + } + + // * 3. 출력 + System.out.println(answer); + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n+1]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + arr[n] = 0; + } +} From f31900560591d5b4101d43b32b1ab26c5e29bf42 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 29 Sep 2022 13:40:06 +0900 Subject: [PATCH 091/163] =?UTF-8?q?[BOJ-5558-JAVA]=201=ED=95=99=EB=85=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_5557.java | 78 ++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_5557.java diff --git a/java/BOJ/Gold/V/G5_5557.java b/java/BOJ/Gold/V/G5_5557.java new file mode 100644 index 0000000..8b80a2a --- /dev/null +++ b/java/BOJ/Gold/V/G5_5557.java @@ -0,0 +1,78 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/5557 + * + * ? 제목: 1학년 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 상근이가 1학년 때, 덧셈, 뺄셈을 매우 좋아했다. 상근이는 숫자가 줄 지어있는 것을 보기만 하면, 마지막 두 숫자 사이에 '='을 넣고, 나머지 숫자 사이에는 '+' 또는 '-'를 넣어 등식을 만들며 놀고 있다. 예를 들어, "8 3 2 4 8 7 2 4 0 8 8"에서 등식 "8+3-2-4+8-7-2-4-0+8=8"을 만들 수 있다. + * 상근이는 올바른 등식을 만들려고 한다. 상근이는 아직 학교에서 음수를 배우지 않았고, 20을 넘는 수는 모른다. 따라서, 왼쪽부터 계산할 때, 중간에 나오는 수가 모두 0 이상 20 이하이어야 한다. 예를 들어, "8+3+2-4-8-7+2+4+0+8=8"은 올바른 등식이지만, 8+3+2-4-8-7이 음수이기 때문에, 상근이가 만들 수 없는 등식이다. + * 숫자가 주어졌을 때, 상근이가 만들 수 있는 올바른 등식의 수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 숫자의 개수 N이 주어진다. (3 ≤ N ≤ 100) 둘째 줄에는 0 이상 9 이하의 정수 N개가 공백으로 구분해 주어진다. + * + * 11 -> n + * 8 3 2 4 8 7 2 4 0 8 8 -> arr[0] ~ arr[n-1] + * + * ? 출력 + * 첫째 줄에 상근이가 만들 수 있는 올바른 등식의 개수를 출력한다. 이 값은 263-1 이하이다. + * + * 10 + * + * ? 채점 결과 + * * 시간: 0.076초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G5_5557 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n; + static int[] arr; + + public static void main(String[] args) throws IOException { + input(); + + long[][] dp = new long[n][21]; + dp[0][arr[0]] = 1; + + for (int i = 1; i < n; i++) { + for (int j = 0; j <= 20; j++) { + if (dp[i - 1][j] > 0) { + if (j + arr[i] <= 20) { + dp[i][j + arr[i]] += dp[i - 1][j]; + } + + if (j - arr[i] >= 0) { + dp[i][j - arr[i]] += dp[i - 1][j]; + } + } + } + } + + System.out.println(dp[n - 2][arr[n - 1]]); + } + + public static void input() throws IOException { + 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()); + } + + } +} From 7247417260493801552e0bb805f513940740e8a2 Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 30 Sep 2022 11:52:43 +0900 Subject: [PATCH 092/163] =?UTF-8?q?[BOJ-1240-JAVA]=20=EB=85=B8=EB=93=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=EC=9D=98=20=EA=B1=B0=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_1240_BFS.java | 120 +++++++++++++++++++++++++++++ java/BOJ/Gold/V/G5_1240_FLOYD.java | 106 +++++++++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_1240_BFS.java create mode 100644 java/BOJ/Gold/V/G5_1240_FLOYD.java diff --git a/java/BOJ/Gold/V/G5_1240_BFS.java b/java/BOJ/Gold/V/G5_1240_BFS.java new file mode 100644 index 0000000..90d7352 --- /dev/null +++ b/java/BOJ/Gold/V/G5_1240_BFS.java @@ -0,0 +1,120 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1240 + * + * ? 제목: 노드사이의 거리 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * N(2≤N≤1,000)개의 노드로 이루어진 트리가 주어지고 M(M≤1,000)개의 두 노드 쌍을 입력받을 때 두 노드 사이의 거리를 출력하라. + * + * ? 입력 & 파싱 + * 첫째 줄에 노드의 개수 N이 입력되고 다음 N-1개의 줄에 트리 상에 연결된 두 점과 거리(10,000 이하의 정수)를 입력받는다. 그 다음 줄에는 거리를 알고 싶은 M개의 노드 쌍이 한 줄에 한 쌍씩 입력된다. + * + * 4 2 -> n m + * 2 1 2 -> a b c + * 4 3 2 + * 1 4 3 + * 1 2 -> a b + * 3 2 + * + * ? 출력 + * M개의 줄에 차례대로 입력받은 두 노드 사이의 거리를 출력한다. + * + * 2 + * 7 + * + * ? 채점 결과 + * * 시간: 0.276초 + * * 메모리: 48MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G5_1240_BFS { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static ArrayList[] arr; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + StringBuffer sb = new StringBuffer(); + + // * 2. BFS + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + sb.append(bfs(a, b) + "\n"); + } + + // * 3. 출력 + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // * a -> b 로 가는 BFS + public static int bfs(int a, int b) { + boolean[] visit = new boolean[n+1]; + Queue queue = new LinkedList<>(); + visit[a] = true; + queue.add(new int[] {a, 0}); + + while(!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == b) { + return cur[1]; + } + + for (int[] next : arr[cur[0]]) { + if (!visit[next[0]]) { + visit[next[0]] = true; + queue.add(new int[] {next[0], cur[1] + next[1]}); + } + } + + } + + return -1; + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new ArrayList[n+1]; + for (int i = 1; i <= n; i++) { + arr[i] = new ArrayList<>(); + } + + for (int i = 0; i < n-1; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + arr[a].add(new int[] {b, c}); + arr[b].add(new int[] {a, c}); + } + } +} diff --git a/java/BOJ/Gold/V/G5_1240_FLOYD.java b/java/BOJ/Gold/V/G5_1240_FLOYD.java new file mode 100644 index 0000000..6a17ef3 --- /dev/null +++ b/java/BOJ/Gold/V/G5_1240_FLOYD.java @@ -0,0 +1,106 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1240 + * + * ? 제목: 노드사이의 거리 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * N(2≤N≤1,000)개의 노드로 이루어진 트리가 주어지고 M(M≤1,000)개의 두 노드 쌍을 입력받을 때 두 노드 사이의 거리를 출력하라. + * + * ? 입력 & 파싱 + * 첫째 줄에 노드의 개수 N이 입력되고 다음 N-1개의 줄에 트리 상에 연결된 두 점과 거리(10,000 이하의 정수)를 입력받는다. 그 다음 줄에는 거리를 알고 싶은 M개의 노드 쌍이 한 줄에 한 쌍씩 입력된다. + * + * 4 2 -> n m + * 2 1 2 -> a b c + * 4 3 2 + * 1 4 3 + * 1 2 -> a b + * 3 2 + * + * ? 출력 + * M개의 줄에 차례대로 입력받은 두 노드 사이의 거리를 출력한다. + * + * 2 + * 7 + * + * ? 채점 결과 + * * 시간: 2.02초 + * * 메모리: 22MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.StringTokenizer; + +public class G5_1240_FLOYD { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[][] arr; + + // * 거리 최댓값 + static int MAX = 10_000_000; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 플로이드-와샬 + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (k == i || k == j) { + continue; + } + + if (arr[i][j] > arr[i][k] + arr[k][j]) { + arr[i][j] = arr[i][k] + arr[k][j]; + } + } + } + } + + // * 3. 출력 + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + bw.write(arr[a][b] + "\n"); + } + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n+1][n+1]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + arr[i][j] = MAX; + } + } + + for (int i = 0; i < n-1; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + arr[a][b] = c; + arr[b][a] = c; + } + } +} From 091f61062e292e43b97c59b6fed0af097a9d704c Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 1 Oct 2022 15:01:35 +0900 Subject: [PATCH 093/163] =?UTF-8?q?[BOJ-7579-JAVA]=20=EC=95=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_7579.java | 117 +++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_7579.java diff --git a/java/BOJ/Gold/III/G3_7579.java b/java/BOJ/Gold/III/G3_7579.java new file mode 100644 index 0000000..c5f4884 --- /dev/null +++ b/java/BOJ/Gold/III/G3_7579.java @@ -0,0 +1,117 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/7579 + * + * ? 제목: 앱 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 우리는 스마트폰을 사용하면서 여러 가지 앱(App)을 실행하게 된다. 대개의 경우 화면에 보이는 ‘실행 중’인 앱은 하나뿐이지만 보이지 않는 상태로 많은 앱이 '활성화'되어 있다. 앱들이 활성화 되어 있다는 것은 화면에 보이지 않더라도 메인 메모리에 직전의 상태가 기록되어 있는 것을 말한다. 현재 실행 중이 아니더라도 이렇게 메모리에 남겨두는 이유는 사용자가 이전에 실행하던 앱을 다시 불러올 때에 직전의 상태를 메인 메모리로부터 읽어 들여 실행 준비를 빠르게 마치기 위해서이다. + * 하지만 스마트폰의 메모리는 제한적이기 때문에 한번이라도 실행했던 모든 앱을 활성화된 채로 메인 메모리에 남겨두다 보면 메모리 부족 상태가 오기 쉽다. 새로운 앱을 실행시키기 위해 필요한 메모리가 부족해지면 스마트폰의 운영체제는 활성화 되어 있는 앱들 중 몇 개를 선택하여 메모리로부터 삭제하는 수밖에 없다. 이러한 과정을 앱의 ‘비활성화’라고 한다. + * 메모리 부족 상황에서 활성화 되어 있는 앱들을 무작위로 필요한 메모리만큼 비활성화 하는 것은 좋은 방법이 아니다. 비활성화된 앱들을 재실행할 경우 그만큼 시간이 더 필요하기 때문이다. 여러분은 이러한 앱의 비활성화 문제를 스마트하게 해결하기 위한 프로그램을 작성해야 한다 + * 현재 N개의 앱, A1, ..., AN이 활성화 되어 있다고 가정하자. 이들 앱 Ai는 각각 mi 바이트만큼의 메모리를 사용하고 있다. 또한, 앱 Ai를 비활성화한 후에 다시 실행하고자 할 경우, 추가적으로 들어가는 비용(시간 등)을 수치화 한 것을 ci 라고 하자. 이러한 상황에서 사용자가 새로운 앱 B를 실행하고자 하여, 추가로 M 바이트의 메모리가 필요하다고 하자. 즉, 현재 활성화 되어 있는 앱 A1, ..., AN 중에서 몇 개를 비활성화 하여 M 바이트 이상의 메모리를 추가로 확보해야 하는 것이다. 여러분은 그 중에서 비활성화 했을 경우의 비용 ci의 합을 최소화하여 필요한 메모리 M 바이트를 확보하는 방법을 찾아야 한다. + * + * ? 입력 & 파싱 + * 입력은 3줄로 이루어져 있다. 첫 줄에는 정수 N과 M이 공백문자로 구분되어 주어지며, 둘째 줄과 셋째 줄에는 각각 N개의 정수가 공백문자로 구분되어 주어진다. 둘째 줄의 N개의 정수는 현재 활성화 되어 있는 앱 A1, ..., AN이 사용 중인 메모리의 바이트 수인 m1, ..., mN을 의미하며, 셋째 줄의 정수는 각 앱을 비활성화 했을 경우의 비용 c1, ..., cN을 의미한다 + * 단, 1 ≤ N ≤ 100, 1 ≤ M ≤ 10,000,000이며, 1 ≤ m1, ..., mN ≤ 10,000,000을 만족한다. 또한, 0 ≤ c1, ..., cN ≤ 100이고, M ≤ m1 + m2 + ... + mN이다. + * + * 5 60 -> n m + * 30 10 20 35 40 -> memory[0] ~ memory[n-1] + * 3 0 3 5 4 -> deAct[0] ~ deAct[n-1] + * + * ? 출력 + * 필요한 메모리 M 바이트를 확보하기 위한 앱 비활성화의 최소의 비용을 계산하여 한 줄에 출력해야 한다. + * + * 6 + * + * ? 채점 결과 + * * 시간: 0.868초 + * * 메모리: 57MB + * * 언어: JAVA8 + * * 시도: 5 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.StringTokenizer; + +class App { + public int memory; + public int deAct; + + public App(int memory, int deAct) { + this.memory = memory; + this.deAct = deAct; + } +} + +public class G3_7579 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[] memory; + static int[] deAct; + static ArrayList list = new ArrayList<>(); + + // * 초기 설정 + static int max = 100_000; + static int[] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP + for (int i = 0; i < list.size(); i++) { + App app = list.get(i); + for (int j = m; j >= 0; j--) { + if (dp[j] == max) { + continue; + } + + // 메모리를 M보다 더 많이 확보할 수 있는 경우도 M크기의 메모리 확보하는 것으로 치환 + if (j + app.memory > m) { + dp[m] = Math.min(dp[m], dp[j] + app.deAct); + } else { + dp[j+app.memory] = Math.min(dp[j+app.memory], dp[j] + app.deAct); + } + } + } + + // * 3. 출력 + System.out.println(dp[m]); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + memory = new int[n]; + deAct = new int[n]; + dp = new int[m+1]; + Arrays.fill(dp, max); + dp[0] = 0; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + memory[i] = Integer.parseInt(st.nextToken()); + } + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + deAct[i] = Integer.parseInt(st.nextToken()); + } + + for (int i = 0; i < n; i++) { + list.add(new App(memory[i], deAct[i])); + } + + list.sort((a, b) -> a.deAct - b.deAct); + } +} From 528394ac507389a087ba5fb152966feacce049c1 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 2 Oct 2022 13:41:44 +0900 Subject: [PATCH 094/163] =?UTF-8?q?[BOJ-2239-JAVA]=20=EC=8A=A4=EB=8F=84?= =?UTF-8?q?=EC=BF=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_2239.java | 144 ++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_2239.java diff --git a/java/BOJ/Gold/IV/G4_2239.java b/java/BOJ/Gold/IV/G4_2239.java new file mode 100644 index 0000000..d28d09f --- /dev/null +++ b/java/BOJ/Gold/IV/G4_2239.java @@ -0,0 +1,144 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2239 + * + * ? 제목: 스도쿠 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다음을 보자. + * 위 그림은 참 잘도 스도쿠 퍼즐을 푼 경우이다. 각 행에 1부터 9까지의 숫자가 중복 없이 나오고, 각 열에 1부터 9까지의 숫자가 중복 없이 나오고, 각 3×3짜리 사각형(9개이며, 위에서 색깔로 표시되었다)에 1부터 9까지의 숫자가 중복 없이 나오기 때문이다. + * 하다 만 스도쿠 퍼즐이 주어졌을 때, 마저 끝내는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 9개의 줄에 9개의 숫자로 보드가 입력된다. 아직 숫자가 채워지지 않은 칸에는 0이 주어진다. + * + * 103000509 -> arr[0][0] ~ arr[0][8] + * 002109400 + * 000704000 + * 300502006 + * 060000050 + * 700803004 + * 000401000 + * 009205800 + * 804000107 -> arr[8][0] ~ arr[8][8] + * + * ? 출력 + * 9개의 줄에 9개의 숫자로 답을 출력한다. 답이 여러 개 있다면 그 중 사전식으로 앞서는 것을 출력한다. 즉, 81자리의 수가 제일 작은 경우를 출력한다. + * + * 143628579 + * 572139468 + * 986754231 + * 391542786 + * 468917352 + * 725863914 + * 237481695 + * 619275843 + * 854396127 + * + * ? 채점 결과 + * * 시간: 0.384초 + * * 메모리: 133MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +import java.io.*; +import java.util.ArrayList; + +public class G4_2239 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + static int[][] arr = new int[9][9]; + + // * 초기 설정 + static ArrayList blanks = new ArrayList<>(); + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + backTracking(0); // * 2. 백트래킹 후 성공사례 나오자마자 출력 + } + + // 백트래킹 + public static void backTracking(int len) throws IOException { + // * 빈칸인 곳을 모두 채우기 성공한 경우 + if (len == blanks.size()) { + print(); + System.exit(0); + } + + boolean[] nums = new boolean[10]; + int curX = blanks.get(len)[0]; + int curY = blanks.get(len)[1]; + + // * 가로 & 세로에 있는 숫자들 제거 + for (int i = 0; i < 9; i++) { + if (arr[curX][i] != 0) { + nums[arr[curX][i]] = true; + } + + if (arr[i][curY] != 0) { + nums[arr[i][curY]] = true; + } + } + + // * 같은 3x3 네모칸에 있는 숫자들 제거 + int startX = (curX / 3) * 3; + int startY = (curY / 3) * 3; + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (arr[startX+i][startY+j] != 0) { + nums[arr[startX+i][startY+j]] = true; + } + } + } + + // * 제거되고 남아있는 숫자들을 for 문을 돌려서 백트래킹 + for (int i = 1; i < 10; i++) { + if (!nums[i]) { + arr[curX][curY] = i; + backTracking(len+1); + arr[curX][curY] = 0; + } + } + + } + + // 스도쿠 배열 출력 + public static void print() throws IOException { + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 9; j++) { + sb.append(arr[i][j]); + } + sb.append("\n"); + } + + bw.write(sb.toString()); + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + for (int i = 0; i < 9; i++) { + char[] line = br.readLine().toCharArray(); + for (int j = 0; j < 9; j++) { + arr[i][j] = line[j] - '0'; + + if (arr[i][j] == 0) { + blanks.add(new int[] {i, j}); + } + } + } + + } + +} From 4412d3c7877f1118fab8b0b7621429b9a93c1aba Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 3 Oct 2022 13:26:53 +0900 Subject: [PATCH 095/163] =?UTF-8?q?fail:=20[BOJ-2098-JAVA]=20=EC=99=B8?= =?UTF-8?q?=ED=8C=90=EC=9B=90=20=EC=88=9C=ED=9A=8C(58%=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=EC=B4=88=EA=B3=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/failed/G1_2098.java | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 java/BOJ/failed/G1_2098.java diff --git a/java/BOJ/failed/G1_2098.java b/java/BOJ/failed/G1_2098.java new file mode 100644 index 0000000..91fb0d6 --- /dev/null +++ b/java/BOJ/failed/G1_2098.java @@ -0,0 +1,66 @@ +/** + * ? https://www.acmicpc.net/problem/2098 + * ? 58% 시간초과 + */ +package failed; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G1_2098 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n; + static int MAX = 987654321; + static int[][] dist; + static int[][] arr; + + public static void main(String[] args) throws IOException { + input(); + dfs(0, 1); + System.out.println(dist[0][1]); + } + + public static int dfs(int cur, int visit) { + if (visit == (1 << n) - 1) { + if (arr[cur][0] == 0) { + return MAX; + } + return arr[cur][0]; + } + + if (dist[cur][visit] != MAX) { + return dist[cur][visit]; + } + + for (int i = 0; i < n; i++) { + if ((visit & (1 << i)) == 0 && arr[cur][i] != 0) { + dist[cur][visit] = Math.min(dist[cur][visit], + dfs(i, visit | (1 << i)) + arr[cur][i]); + } + } + + return dist[cur][visit]; + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n][n]; + dist = new int[n][(1 << n)]; + for (int[] d : dist) { + Arrays.fill(d, MAX); + } + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 0547616bc6ac9bc5ae30eaad7c65429b22d63bd2 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 3 Oct 2022 19:14:12 +0900 Subject: [PATCH 096/163] =?UTF-8?q?[BOJ-2617-JAVA]=20=EA=B5=AC=EC=8A=AC=20?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_2617.java | 110 ++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_2617.java diff --git a/java/BOJ/Gold/IV/G4_2617.java b/java/BOJ/Gold/IV/G4_2617.java new file mode 100644 index 0000000..4f31696 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_2617.java @@ -0,0 +1,110 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2617 + * + * ? 제목: 구슬 찾기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 모양은 같으나, 무게가 모두 다른 N개의 구슬이 있다. N은 홀수이며, 구슬에는 번호가 1,2,...,N으로 붙어 있다. 이 구슬 중에서 무게가 전체의 중간인 (무게 순서로 (N+1)/2번째) 구슬을 찾기 위해서 아래와 같은 일을 하려 한다. + * 우리에게 주어진 것은 양팔 저울이다. 한 쌍의 구슬을 골라서 양팔 저울의 양쪽에 하나씩 올려 보면 어느 쪽이 무거운가를 알 수 있다. 이렇게 M개의 쌍을 골라서 각각 양팔 저울에 올려서 어느 것이 무거운가를 모두 알아냈다. 이 결과를 이용하여 무게가 중간이 될 가능성이 전혀 없는 구슬들은 먼저 제외한다. + * 예를 들어, N=5이고, M=4 쌍의 구슬에 대해서 어느 쪽이 무거운가를 알아낸 결과가 아래에 있다. + * + * 구슬 2번이 구슬 1번보다 무겁다. + * 구슬 4번이 구슬 3번보다 무겁다. + * 구슬 5번이 구슬 1번보다 무겁다. + * 구슬 4번이 구슬 2번보다 무겁다. + * + * 위와 같이 네 개의 결과만을 알고 있으면, 무게가 중간인 구슬을 정확하게 찾을 수는 없지만, 1번 구슬과 4번 구슬은 무게가 중간인 구슬이 절대 될 수 없다는 것은 확실히 알 수 있다. 1번 구슬보다 무거운 것이 2, 4, 5번 구슬이고, 4번 보다 가벼운 것이 1, 2, 3번이다. 따라서 답은 2개이다. + * M 개의 쌍에 대한 결과를 보고 무게가 중간인 구슬이 될 수 없는 구슬의 개수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫 줄은 구슬의 개수를 나타내는 정수 N(1 ≤ N ≤ 99)과 저울에 올려 본 쌍의 개수 M(1 ≤ M ≤ N(N-1)/2)이 주어진다. 그 다음 M 개의 줄은 각 줄마다 두 개의 구슬 번호가 주어지는데, 앞 번호의 구슬이 뒤 번호의 구슬보다 무겁다는 것을 뜻한다. + * + * 5 4 -> n m + * 2 1 -> a b + * 4 3 -> a b + * 5 1 -> a b + * 4 2 -> a b + * + * ? 출력 + * 첫 줄에 무게가 중간이 절대로 될 수 없는 구슬의 수를 출력 한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 0.148초 + * * 메모리: 13MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G4_2617 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + public static void main(String[] args) throws IOException { + int answer = 0; + + // * 1. 입력 받기 + st = new StringTokenizer(br.readLine()); + int n = Integer.parseInt(st.nextToken()); + int m = Integer.parseInt(st.nextToken()); + + int[][] arr = new int[n+1][n+1]; + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + arr[a][b] = 1; + arr[b][a] = 2; + } + + // * 2. 플로이드-와샬 + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (k == i || i == j) { + continue; + } + + if (arr[i][k] == 1 && arr[k][j] == 1) { + arr[i][j] = 1; + } else if (arr[i][k] == 2 && arr[k][j] == 2) { + arr[i][j] = 2; + } + } + } + } + + // * 3. 본인보다 무겁거나 가벼운것들의 갯수가 반을 넘어갈 경우 카운트+1 + for (int i = 1; i <= n; i++) { + int c1 = 0; + int c2 = 0; + + for (int j = 1; j <= n; j++) { + if (arr[i][j] == 1) { + c1++; + } else if (arr[i][j] == 2) { + c2++; + } + } + + if (c1 >= (n/2) + 1 || c2 >= (n/2) + 1) { + answer++; + } + } + + // * 4. 출력 + System.out.println(answer); + } +} From 584131ba6d1fb175850ef394d3245be640c55f4e Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 4 Oct 2022 14:21:23 +0900 Subject: [PATCH 097/163] =?UTF-8?q?[BOJ-2098-JAVA]=20=EC=99=B8=ED=8C=90?= =?UTF-8?q?=EC=9B=90=20=EC=88=9C=ED=9A=8C=20=ED=86=B5=EA=B3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_2098.java | 104 +++++++++++++++++++++++++++++++++++ java/BOJ/failed/G1_2098.java | 66 ---------------------- 2 files changed, 104 insertions(+), 66 deletions(-) create mode 100644 java/BOJ/Gold/I/G1_2098.java delete mode 100644 java/BOJ/failed/G1_2098.java diff --git a/java/BOJ/Gold/I/G1_2098.java b/java/BOJ/Gold/I/G1_2098.java new file mode 100644 index 0000000..9be4db1 --- /dev/null +++ b/java/BOJ/Gold/I/G1_2098.java @@ -0,0 +1,104 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2098 + * + * ? 제목: 외판원 순회 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 외판원 순회 문제는 영어로 Traveling Salesman problem (TSP) 라고 불리는 문제로 computer science 분야에서 가장 중요하게 취급되는 문제 중 하나이다. 여러 가지 변종 문제가 있으나, 여기서는 가장 일반적인 형태의 문제를 살펴보자. + * 1번부터 N번까지 번호가 매겨져 있는 도시들이 있고, 도시들 사이에는 길이 있다. (길이 없을 수도 있다) 이제 한 외판원이 어느 한 도시에서 출발해 N개의 도시를 모두 거쳐 다시 원래의 도시로 돌아오는 순회 여행 경로를 계획하려고 한다. 단, 한 번 갔던 도시로는 다시 갈 수 없다. (맨 마지막에 여행을 출발했던 도시로 돌아오는 것은 예외) 이런 여행 경로는 여러 가지가 있을 수 있는데, 가장 적은 비용을 들이는 여행 계획을 세우고자 한다. + * 각 도시간에 이동하는데 드는 비용은 행렬 W[i][j]형태로 주어진다. W[i][j]는 도시 i에서 도시 j로 가기 위한 비용을 나타낸다. 비용은 대칭적이지 않다. 즉, W[i][j] 는 W[j][i]와 다를 수 있다. 모든 도시간의 비용은 양의 정수이다. W[i][i]는 항상 0이다. 경우에 따라서 도시 i에서 도시 j로 갈 수 없는 경우도 있으며 이럴 경우 W[i][j]=0이라고 하자. + * N과 비용 행렬이 주어졌을 때, 가장 적은 비용을 들이는 외판원의 순회 여행 경로를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 16) 다음 N개의 줄에는 비용 행렬이 주어진다. 각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다. W[i][j]는 도시 i에서 j로 가기 위한 비용을 나타낸다. + * 항상 순회할 수 있는 경우만 입력으로 주어진다. + * + * 4 -> n + * 0 10 15 20 -> arr[0][0] ~ arr[0][n-1] + * 5 0 9 10 + * 6 13 0 12 + * 8 8 9 0 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 첫째 줄에 외판원의 순회에 필요한 최소 비용을 출력한다. + * + * 35 + * + * ? 채점 결과 + * * 시간: 0.152초 + * * 메모리: 17MB + * * 언어: JAVA8 + * * 시도: 10+ + */ +package Gold.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G1_2098 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[][] arr; + + // * 초기 설정 + static int MAX = 987654321; + static int[][] dist; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기. + System.out.println(dfs(0, 1)); // * 2. TSP 알고리즘 + 정답 출력 + } + + // * TSP(외판원 순회 알고리즘) : Travelling Salesman Problem + public static int dfs(int cur, int visit) { + if (visit == (1 << n) - 1) { + if (arr[cur][0] == 0) { + return MAX; + } + return arr[cur][0]; + } + + if (dist[cur][visit] != -1) { + return dist[cur][visit]; + } + + dist[cur][visit] = MAX; + + for (int i = 0; i < n; i++) { + if ((visit & (1 << i)) != 0 || arr[cur][i] == 0) { + continue; + } + dist[cur][visit] = Math.min(dist[cur][visit], + dfs(i, visit | (1 << i)) + arr[cur][i]); + } + + return dist[cur][visit]; + } + + // * 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n][n]; + dist = new int[n][(1 << n) - 1]; + for (int[] d : dist) { + Arrays.fill(d, -1); + } + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} diff --git a/java/BOJ/failed/G1_2098.java b/java/BOJ/failed/G1_2098.java deleted file mode 100644 index 91fb0d6..0000000 --- a/java/BOJ/failed/G1_2098.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * ? https://www.acmicpc.net/problem/2098 - * ? 58% 시간초과 - */ -package failed; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Arrays; -import java.util.StringTokenizer; - -public class G1_2098 { - static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - static StringTokenizer st; - - static int n; - static int MAX = 987654321; - static int[][] dist; - static int[][] arr; - - public static void main(String[] args) throws IOException { - input(); - dfs(0, 1); - System.out.println(dist[0][1]); - } - - public static int dfs(int cur, int visit) { - if (visit == (1 << n) - 1) { - if (arr[cur][0] == 0) { - return MAX; - } - return arr[cur][0]; - } - - if (dist[cur][visit] != MAX) { - return dist[cur][visit]; - } - - for (int i = 0; i < n; i++) { - if ((visit & (1 << i)) == 0 && arr[cur][i] != 0) { - dist[cur][visit] = Math.min(dist[cur][visit], - dfs(i, visit | (1 << i)) + arr[cur][i]); - } - } - - return dist[cur][visit]; - } - - public static void input() throws IOException { - n = Integer.parseInt(br.readLine()); - - arr = new int[n][n]; - dist = new int[n][(1 << n)]; - for (int[] d : dist) { - Arrays.fill(d, MAX); - } - - for (int i = 0; i < n; i++) { - st = new StringTokenizer(br.readLine()); - for (int j = 0; j < n; j++) { - arr[i][j] = Integer.parseInt(st.nextToken()); - } - } - } -} From 331135d368051d935db5cf0ffa791143a53821f1 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 5 Oct 2022 12:22:56 +0900 Subject: [PATCH 098/163] =?UTF-8?q?[BOJ-2467-JAVA]=20=EC=9A=A9=EC=95=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2467.java | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2467.java diff --git a/java/BOJ/Gold/V/G5_2467.java b/java/BOJ/Gold/V/G5_2467.java new file mode 100644 index 0000000..df47752 --- /dev/null +++ b/java/BOJ/Gold/V/G5_2467.java @@ -0,0 +1,103 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2467 + * + * ? 제목: 용액 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * KOI 부설 과학연구소에서는 많은 종류의 산성 용액과 알칼리성 용액을 보유하고 있다. 각 용액에는 그 용액의 특성을 나타내는 하나의 정수가 주어져있다. 산성 용액의 특성값은 1부터 1,000,000,000까지의 양의 정수로 나타내고, 알칼리성 용액의 특성값은 -1부터 -1,000,000,000까지의 음의 정수로 나타낸다. + * 같은 양의 두 용액을 혼합한 용액의 특성값은 혼합에 사용된 각 용액의 특성값의 합으로 정의한다. 이 연구소에서는 같은 양의 두 용액을 혼합하여 특성값이 0에 가장 가까운 용액을 만들려고 한다. + * 예를 들어, 주어진 용액들의 특성값이 [-99, -2, -1, 4, 98]인 경우에는 특성값이 -99인 용액과 특성값이 98인 용액을 혼합하면 특성값이 -1인 용액을 만들 수 있고, 이 용액의 특성값이 0에 가장 가까운 용액이다. 참고로, 두 종류의 알칼리성 용액만으로나 혹은 두 종류의 산성 용액만으로 특성값이 0에 가장 가까운 혼합 용액을 만드는 경우도 존재할 수 있다. + * 산성 용액과 알칼리성 용액의 특성값이 정렬된 순서로 주어졌을 때, 이 중 두 개의 서로 다른 용액을 혼합하여 특성값이 0에 가장 가까운 용액을 만들어내는 두 용액을 찾는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에는 전체 용액의 수 N이 입력된다. N은 2 이상 100,000 이하의 정수이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 오름차순으로 입력되며, 이 수들은 모두 -1,000,000,000 이상 1,000,000,000 이하이다. N개의 용액들의 특성값은 모두 서로 다르고, 산성 용액만으로나 알칼리성 용액만으로 입력이 주어지는 경우도 있을 수 있다. + * + * 5 -> n + * -99 -2 -1 4 98 -> arr[0] ~ arr[n-1] + * + * ? 출력 + * 첫째 줄에 특성값이 0에 가장 가까운 용액을 만들어내는 두 용액의 특성값을 출력한다. 출력해야 하는 두 용액은 특성값의 오름차순으로 출력한다. 특성값이 0에 가장 가까운 용액을 만들어내는 경우가 두 개 이상일 경우에는 그 중 아무것이나 하나를 출력한다. + * + * -99 98 + * + * ? 채점 결과 + * * 시간: 0.296초 + * * 메모리: 32MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.V; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G5_2467 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int max = Integer.MAX_VALUE; + static int[] result; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 이분탐색 + for (int i = 0; i < n; i++) { + int left = 0; + int right = n - 1; + int val = arr[i]; + + while (left <= right) { + int mid = (left + right) / 2; + int sum = val + arr[mid]; + + if (Math.abs(sum) <= max && mid != i) { + max = Math.abs(sum); + result[0] = arr[i]; + result[1] = arr[mid]; + } + + if (sum > 0) { + right = mid - 1; + } else { + left = mid + 1; + } + } + } + + // * 3. 출력 + if (result[0] > result[1]) { + bw.write(result[1] + " " + result[0]); + } else { + bw.write(result[0] + " " + result[1]); + } + + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n]; + result = new int[2]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + + Arrays.sort(arr); + } +} From a9f04de839ed56aaf83a62d615a051b01eff9f97 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 5 Oct 2022 12:23:21 +0900 Subject: [PATCH 099/163] =?UTF-8?q?[BOJ-2470-JAVA]=20=EB=91=90=20=EC=9A=A9?= =?UTF-8?q?=EC=95=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2470.java | 101 +++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2470.java diff --git a/java/BOJ/Gold/V/G5_2470.java b/java/BOJ/Gold/V/G5_2470.java new file mode 100644 index 0000000..45314e9 --- /dev/null +++ b/java/BOJ/Gold/V/G5_2470.java @@ -0,0 +1,101 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2470 + * + * ? 제목: 두 용액 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * KOI 부설 과학연구소에서는 많은 종류의 산성 용액과 알칼리성 용액을 보유하고 있다. 각 용액에는 그 용액의 특성을 나타내는 하나의 정수가 주어져있다. 산성 용액의 특성값은 1부터 1,000,000,000까지의 양의 정수로 나타내고, 알칼리성 용액의 특성값은 -1부터 -1,000,000,000까지의 음의 정수로 나타낸다. + * 같은 양의 두 용액을 혼합한 용액의 특성값은 혼합에 사용된 각 용액의 특성값의 합으로 정의한다. 이 연구소에서는 같은 양의 두 용액을 혼합하여 특성값이 0에 가장 가까운 용액을 만들려고 한다. + * 예를 들어, 주어진 용액들의 특성값이 [-2, 4, -99, -1, 98]인 경우에는 특성값이 -99인 용액과 특성값이 98인 용액을 혼합하면 특성값이 -1인 용액을 만들 수 있고, 이 용액이 특성값이 0에 가장 가까운 용액이다. 참고로, 두 종류의 알칼리성 용액만으로나 혹은 두 종류의 산성 용액만으로 특성값이 0에 가장 가까운 혼합 용액을 만드는 경우도 존재할 수 있다. + * 산성 용액과 알칼리성 용액의 특성값이 주어졌을 때, 이 중 두 개의 서로 다른 용액을 혼합하여 특성값이 0에 가장 가까운 용액을 만들어내는 두 용액을 찾는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에는 전체 용액의 수 N이 입력된다. N은 2 이상 100,000 이하이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 수들은 모두 -1,000,000,000 이상 1,000,000,000 이하이다. N개의 용액들의 특성값은 모두 다르고, 산성 용액만으로나 알칼리성 용액만으로 입력이 주어지는 경우도 있을 수 있다. + * + * 5 -> n + * -2 4 -99 -1 98 -> arr[0] ~ arr[n-1] + * + * ? 출력 + * 첫째 줄에 특성값이 0에 가장 가까운 용액을 만들어내는 두 용액의 특성값을 출력한다. 출력해야 하는 두 용액은 특성값의 오름차순으로 출력한다. 특성값이 0에 가장 가까운 용액을 만들어내는 경우가 두 개 이상일 경우에는 그 중 아무것이나 하나를 출력한다. + * + * -99 98 + * + * ? 채점 결과 + * * 시간: 0.312초 + * * 메모리: 31MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class G5_2470 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n; + static int[] arr; + static int max = Integer.MAX_VALUE; + static int[] result; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 이분탐색 + for (int i = 0; i < n; i++) { + int left = 0; + int right = n - 1; + int val = arr[i]; + + while (left <= right) { + int mid = (left + right) / 2; + int sum = val + arr[mid]; + + if (Math.abs(sum) <= max && mid != i) { + max = Math.abs(sum); + result[0] = arr[i]; + result[1] = arr[mid]; + } + + if (sum > 0) { + right = mid - 1; + } else { + left = mid + 1; + } + } + } + + // * 3. 출력 + if (result[0] > result[1]) { + bw.write(result[1] + " " + result[0]); + } else { + bw.write(result[0] + " " + result[1]); + } + + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n]; + result = new int[2]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + + // * 정렬 + Arrays.sort(arr); + } +} From e1700966e70ae2f7b7d03f6a4c7cbf3b9e0b35db Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 6 Oct 2022 13:40:56 +0900 Subject: [PATCH 100/163] =?UTF-8?q?[BOJ-2166-JAVA]=20=EB=8B=A4=EA=B0=81?= =?UTF-8?q?=ED=98=95=EC=9D=98=20=EB=A9=B4=EC=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2166.java | 94 ++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2166.java diff --git a/java/BOJ/Gold/V/G5_2166.java b/java/BOJ/Gold/V/G5_2166.java new file mode 100644 index 0000000..519817f --- /dev/null +++ b/java/BOJ/Gold/V/G5_2166.java @@ -0,0 +1,94 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2166 + * + * ? 제목: 다각형의 면적 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 2차원 평면상에 N(3 ≤ N ≤ 10,000)개의 점으로 이루어진 다각형이 있다. 이 다각형의 면적을 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 N이 주어진다. 다음 N개의 줄에는 다각형을 이루는 순서대로 N개의 점의 x, y좌표가 주어진다. 좌표값은 절댓값이 100,000을 넘지 않는 정수이다. + * + * 4 -> n + * 0 0 -> points.get(0) + * 0 10 + * 10 10 + * 10 0 -> points.get(n-1) + * + * ? 출력 + * 첫째 줄에 면적을 출력한다. 면적을 출력할 때에는 소수점 아래 둘째 자리에서 반올림하여 첫째 자리까지 출력한다. + * + * 100.0 + * + * ? 채점 결과 + * * 시간: 0.152초 + * * 메모리: 17MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +class Point { + long x; + long y; + + public Point(long x, long y) { + this.x = x; + this.y = y; + } +} + +public class G5_2166 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static ArrayList points = new ArrayList<>(); + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 신발끈 정리 + long val1 = 0; + long val2 = 0; + for (int i = 0; i < n; i++) { + val1 += (points.get(i).x * points.get(i+1).y); + val2 += (points.get(i+1).x * points.get(i).y); + } + + // * 3. 출력: 출력값 형변환 + double area = Math.abs(val1 - val2) * 10.0 / 20; + String str = String.valueOf((long) (area * 10)); + String answer = str.substring(0, str.length()-1) + "." + str.substring(str.length()-1); + bw.write(answer); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + long x = Integer.parseInt(st.nextToken()); + long y = Integer.parseInt(st.nextToken()); + + points.add(new Point(x, y)); + } + + points.add(points.get(0)); + } + +} From a7d30a313ea6ba524f448d5660f21b0dd782a384 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 7 Oct 2022 15:12:20 +0900 Subject: [PATCH 101/163] =?UTF-8?q?[BOJ-9328-JAVA]=20=EC=97=B4=EC=87=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_9328.java | 222 +++++++++++++++++++++++++++++++++++ java/BOJ/failed/G1_9328.java | 170 --------------------------- 2 files changed, 222 insertions(+), 170 deletions(-) create mode 100644 java/BOJ/Gold/I/G1_9328.java delete mode 100644 java/BOJ/failed/G1_9328.java diff --git a/java/BOJ/Gold/I/G1_9328.java b/java/BOJ/Gold/I/G1_9328.java new file mode 100644 index 0000000..fb59ca2 --- /dev/null +++ b/java/BOJ/Gold/I/G1_9328.java @@ -0,0 +1,222 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/9328 + * + * ? 제목: 열쇠 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 상근이는 1층 빌딩에 침입해 매우 중요한 문서를 훔쳐오려고 한다. 상근이가 가지고 있는 평면도에는 문서의 위치가 모두 나타나 있다. 빌딩의 문은 모두 잠겨있기 때문에, 문을 열려면 열쇠가 필요하다. 상근이는 일부 열쇠를 이미 가지고 있고, 일부 열쇠는 빌딩의 바닥에 놓여져 있다. 상근이는 상하좌우로만 이동할 수 있다. + * 상근이가 훔칠 수 있는 문서의 최대 개수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스의 수는 100개를 넘지 않는다. + * 각 테스트 케이스의 첫째 줄에는 지도의 높이와 너비 h와 w (2 ≤ h, w ≤ 100)가 주어진다. 다음 h개 줄에는 빌딩을 나타내는 w개의 문자가 주어지며, 각 문자는 다음 중 하나이다. + * + * '.'는 빈 공간을 나타낸다. + * '*'는 벽을 나타내며, 상근이는 벽을 통과할 수 없다. + * '$'는 상근이가 훔쳐야하는 문서이다. + * 알파벳 대문자는 문을 나타낸다. + * 알파벳 소문자는 열쇠를 나타내며, 그 문자의 대문자인 모든 문을 열 수 있다. + * 마지막 줄에는 상근이가 이미 가지고 있는 열쇠가 공백없이 주어진다. 만약, 열쇠를 하나도 가지고 있지 않는 경우에는 "0"이 주어진다. + * 상근이는 처음에는 빌딩의 밖에 있으며, 빌딩 가장자리의 벽이 아닌 곳을 통해 빌딩 안팎을 드나들 수 있다. 각각의 문에 대해서, 그 문을 열 수 있는 열쇠의 개수는 0개, 1개, 또는 그 이상이고, 각각의 열쇠에 대해서, 그 열쇠로 열 수 있는 문의 개수도 0개, 1개, 또는 그 이상이다. 열쇠는 여러 번 사용할 수 있다. + * + * 3 -> t + * 5 17 -> h w + * ***************** -> arr + * .............**$* + * *B*A*P*C**X*Y*.X. + * *y*x*a*p**$*$**$* + * ***************** + * cz -> keys + * 5 11 -> 반복 + * *.********* + * *...*...*x* + * *X*.*.*.*.* + * *$*...*...* + * *********** + * 0 + * 7 7 + * *ABCDE* + * X.....F + * W.$$$.G + * V.$$$.H + * U.$$$.J + * T.....K + * *SQPML* + * irony + * + * ? 출력 + * 각 테스트 케이스 마다, 상근이가 훔칠 수 있는 문서의 최대 개수를 출력한다. + * + * 3 + * 1 + * 0 + * + * ? 채점 결과 + * * 시간: 0.188초 + * * 메모리: 20MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.I; + +import java.io.*; +import java.util.*; + +public class G1_9328 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int h, w; + static char[][] arr; + + // * 초기 설정 + static int keys; // 현재 갖고있는 키 정보(비트마스크) + static int count; // 현재 획득한 문서의 개수 + static boolean[][] visited; // 방문 표시 배열 + + // * 추가 정보 + // ! 키가 없어서 통과하지 못한 문의 위치 + // ex) 0 : [[1, 2], [2,3], ...] -> 현재까지 키가 없어서 통과하지 못한 A(=0)문의 위치들 + static HashMap> map; + static Queue queue; + + // * 상하좌우 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); // 테스트케이스 개수 + for (int i = 0; i < t; i++) { + input(); // * 1. 입력 받기 + + for (int a = 0; a < h; a++) { + for (int b = 0; b < w; b++) { + // * 2. 테두리가 벽이 아닌 곳들을 큐에 삽입(+방문표시) + if (a == 0 || b == 0 || a == h-1 || b == w-1) { + if (arr[a][b] != '*') { + visited[a][b] = true; + queue.add(new int[] {a, b}); + } + } + } + } + + bfs(); // * 3. BFS + + bw.write(String.valueOf(count + "\n")); // * 4. 출력 + } + + br.close(); + bw.flush(); + bw.close(); + } + + public static void bfs() { + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + int x = cur[0]; + int y = cur[1]; + + // 현재 위치가 키인 경우 + if (isKey(arr[x][y])) { + // 새롭게 키를 습득한 경우 + if ((keys & (1 << (arr[x][y] - 'a'))) == 0) { + keys |= (1 << (arr[x][y] - 'a')); // 키 추가 + + // 현재까지 해당 키가 없어서 통과하지 못한 위치들 중 + // 문이 안열려있는 곳("."이 아닌 곳)을 큐에 넣어주고 방문 표시 + // 문이 열렸으므로 빈공간으로 표시 + for (int[] next : map.get(arr[x][y] - 'a')) { + if (arr[next[0]][next[1]] != '.') { + visited[next[0]][next[1]] = true; + queue.add(next); + arr[next[0]][next[1]] = '.'; + } + } + } + // 키를 획득했으므로 빈공간으로 만들어주기 + arr[x][y] = '.'; + } + + // 현재 위치가 방문인 경우 + else if (isDoor(arr[x][y])) { + // 해당 문에 대한 키가 없을 경우 + if (!hasKey(arr[x][y])) { + // map에 해당 위치 추가 + map.get(arr[x][y] - 'A').add(new int[] {x, y}); + continue; + } + } + + // 현재 위치가 문서인 경우 카운트를 증가하고 빈공간으로 표시 + else if (arr[x][y] == '$') { + arr[x][y] = '.'; + count++; + } + + // 상하좌우 중 벽이 아닌 곳만 큐에 삽입(+방문표시) + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (nx < 0 || ny < 0 || nx >= h || ny >= w || visited[nx][ny] || arr[nx][ny] == '*') { + continue; + } + + visited[nx][ny] = true; + queue.add(new int[] {nx, ny}); + } + + } + } + + // 해당 문에 맞는 키를 현재 가지고 있는지 + public static boolean hasKey(char door) { + return (keys & (1 << (door - 'A'))) != 0; + } + + // 현재 위치의 값이 문인지 + public static boolean isDoor(char c) { + return 0 <= c - 'A' && c - 'A' < 26; + } + + // 현재 위치의 값이 키인지 + public static boolean isKey(char c) { + return 0 <= c - 'a' && c - 'a' < 26; + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + h = Integer.parseInt(st.nextToken()); + w = Integer.parseInt(st.nextToken()); + + count = 0; + arr = new char[h][w]; + visited = new boolean[h][w]; + queue = new LinkedList<>(); + + map = new HashMap<>(); + for (int i = 0; i < 26; i++) { + map.put(i, new ArrayList<>()); + } + + for (int i = 0; i < h; i++) { + arr[i] = br.readLine().toCharArray(); + } + + keys = 0; + char[] k = br.readLine().toCharArray(); + + if (k[0] != '0') { + for (char c: k) { + keys |= (1 << (c - 'a')); + } + } + } +} diff --git a/java/BOJ/failed/G1_9328.java b/java/BOJ/failed/G1_9328.java deleted file mode 100644 index 5d4241f..0000000 --- a/java/BOJ/failed/G1_9328.java +++ /dev/null @@ -1,170 +0,0 @@ -package failed; - -import java.io.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.StringTokenizer; - -public class G1_9328 { - static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); - static StringTokenizer st; - static int h, w; - static char[][] arr; - static ArrayList[][] visited; - static int keys; - static int count; - static int[] dx = {1, -1, 0, 0}; - static int[] dy = {0, 0, 1, -1}; - - public static void main(String[] args) throws IOException { - int t = Integer.parseInt(br.readLine()); - for (int i = 0; i < t; i++) { - input(); - find(); - bw.write(String.valueOf(count + "\n")); - } - bw.flush(); - - } - - public static void find() { - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - if (i == 0 || j == 0 || i == h-1 || j == w-1) { - if (isKey(arr[i][j])) { - int nKey = keys | getKey(arr[i][j]); - arr[i][j] = '.'; - bfs(i, j, nKey); - return; - } else if (isDoor(arr[i][j]) && hasKey(arr[i][j], keys)) { - arr[i][j] = '.'; - bfs(i, j, keys); - return; - } else if (arr[i][j] == '$') { - count++; - arr[i][j] = '.'; - bfs(i, j, keys); - return; - } else if (arr[i][j] == '.') { - bfs(i, j, keys); - return; - } - } - } - } - } - - public static void bfs(int x, int y, int key) { - LinkedList queue = new LinkedList<>(); - visited[x][y].add(key); - queue.add(new int[] {x, y, key}); - System.out.println(); - - while (!queue.isEmpty()) { - int[] cur = queue.poll(); - int curX = cur[0]; - int curY = cur[1]; - int curKey = cur[2]; - System.out.println(curX + " " + curY + " " + Integer.toBinaryString(curKey) + " " + visited[curX][curY]); - - for (int i = 0; i < 4; i++) { - int nx = curX + dx[i]; - int ny = curY + dy[i]; - - if (0 <= nx & nx < h && 0 <= ny && ny < w && !alreadyVisited(nx, ny, curKey)) { - visited[nx][ny].add(curKey); - if (isKey(arr[nx][ny])) { - int nextKey = curKey | getKey(arr[nx][ny]); - queue.add(new int[] {nx, ny, nextKey}); - arr[nx][ny] = '.'; - } else if (isDoor(arr[nx][ny]) && hasKey(arr[nx][ny], curKey)) { - queue.add(new int[] {nx, ny, curKey}); - arr[nx][ny] = '.'; - } else if (arr[nx][ny] == '$') { - count++; - queue.add(new int[] {nx, ny, curKey}); - arr[nx][ny] = '.'; - } else if (arr[nx][ny] == '.') { - queue.add(new int[] {nx, ny, curKey}); - } - } else { - for (int a = 0; a < h; a++) { - for (int b = 0; b < w; b++) { - if (a == 0 || b == 0 || a == h-1 || b == w-1 && !alreadyVisited(a, b, curKey)) { - visited[a][b].add(curKey); - if (isKey(arr[a][b])) { - int nextKey = curKey | getKey(arr[a][b]); - queue.add(new int[] {a, b, nextKey}); - arr[a][b] = '.'; - } else if (isDoor(arr[a][b]) && hasKey(arr[a][b], curKey)) { - queue.add(new int[] {a, b, curKey}); - arr[a][b] = '.'; - } else if (arr[a][b] == '$') { - count++; - queue.add(new int[] {a, b, curKey}); - arr[a][b] = '.'; - } else if (arr[a][b] == '.') { - queue.add(new int[] {a, b, curKey}); - } - } - } - } - } - } - } - } - - public static boolean alreadyVisited(int x, int y, int curKey) { - for (int num: visited[x][y]) { - if (curKey == num) return true; - } - return false; - } - - public static boolean isKey(char c) { - return (0 <= c - 'a') && (c - 'a' < 26); - } - - public static int getKey(char key) { - return 1 << (key - 'a'); - } - - public static boolean isDoor(char c) { - return (0 <= c - 'A') && (c - 'A' < 26); - } - - public static boolean hasKey(char door, int key) { - int needKey = 1 << (door - 'A'); - return (key & needKey) != 0; - } - - public static void input() throws IOException { - st = new StringTokenizer(br.readLine()); - h = Integer.parseInt(st.nextToken()); - w = Integer.parseInt(st.nextToken()); - - count = 0; - arr = new char[h][w]; - visited = new ArrayList[h][w]; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - visited[i][j] = new ArrayList(); - } - } - - for (int i = 0; i < h; i++) { - arr[i] = br.readLine().toCharArray(); - } - - char[] k = br.readLine().toCharArray(); - keys = 0; - - if (k[0] != '0') { - for (char c: k) { - keys |= (1 << (c - 'a')); - } - } - } -} From 04e5cec1e5ecc40616a9147f1793094ae4ec73f3 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 8 Oct 2022 14:54:24 +0900 Subject: [PATCH 102/163] =?UTF-8?q?[BOJ-2631-JAVA]=20=EC=A4=84=EC=84=B8?= =?UTF-8?q?=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_2631.java | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_2631.java diff --git a/java/BOJ/Gold/IV/G4_2631.java b/java/BOJ/Gold/IV/G4_2631.java new file mode 100644 index 0000000..244a228 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_2631.java @@ -0,0 +1,118 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2631 + * + * ? 제목: 줄세우기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ?문제 + * KOI 어린이집에는 N명의 아이들이 있다. 오늘은 소풍을 가는 날이다. 선생님은 1번부터 N번까지 번호가 적혀있는 번호표를 아이들의 가슴에 붙여주었다. 선생님은 아이들을 효과적으로 보호하기 위해 목적지까지 번호순서대로 일렬로 서서 걸어가도록 하였다. 이동 도중에 보니 아이들의 번호순서가 바뀌었다. 그래서 선생님은 다시 번호 순서대로 줄을 세우기 위해서 아이들의 위치를 옮기려고 한다. 그리고 아이들이 혼란스러워하지 않도록 하기 위해 위치를 옮기는 아이들의 수를 최소로 하려고 한다. + * 예를 들어, 7명의 아이들이 다음과 같은 순서대로 줄을 서 있다고 하자. + * + * 3 7 5 2 6 1 4 + * + * 아이들을 순서대로 줄을 세우기 위해, 먼저 4번 아이를 7번 아이의 뒤로 옮겨보자. 그러면 다음과 같은 순서가 된다. + * + * 3 7 4 5 2 6 1 + * + * 이제, 7번 아이를 맨 뒤로 옮긴다. + * + * 3 4 5 2 6 1 7 + * + * 다음 1번 아이를 맨 앞으로 옮긴다. + * + * 1 3 4 5 2 6 7 + * + * 마지막으로 2번 아이를 1번 아이의 뒤로 옮기면 번호 순서대로 배치된다. + * + * 1 2 3 4 5 6 7 + * + * 위의 방법으로 모두 4명의 아이를 옮겨 번호 순서대로 줄을 세운다. 위의 예에서 3명의 아이만을 옮겨서는 순서대로 배치할 수가 없다. 따라서, 4명을 옮기는 것이 가장 적은 수의 아이를 옮기는 것이다.* + * N명의 아이들이 임의의 순서로 줄을 서 있을 때, 번호 순서대로 배치하기 위해 옮겨지는 아이의 최소 수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에는 아이들의 수 N이 주어진다. 둘째 줄부터는 1부터 N까지의 숫자가 한 줄에 하나씩 주어진다. N은 2 이상 200 이하의 정수이다. + * + * 7 -> n + * 3 -> arr[0] + * 7 + * 5 + * 2 + * 6 + * 1 + * 4 -> arr[n-1] + * + * ? 출력 + * 첫째 줄에는 번호 순서대로 줄을 세우는데 옮겨지는 아이들의 최소 수를 출력한다. + * + * 4 + * + * ? 채점 결과 + * * 시간: 0.084초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.IV; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class G4_2631 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int[] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. LIS + int p = 1; + dp[0] = arr[0]; + + for (int i = 1; i < n; i++) { + if (arr[i] > dp[p-1]) { + dp[p++] = arr[i]; + } else { + int left = 0; + int right = p-1; + + while (left < right) { + int mid = (left + right) / 2; + + if (dp[mid] == arr[i]) { + left = mid; + break; + } else if (dp[mid] > arr[i]) { + right = mid-1; + } else { + left = mid+1; + } + } + + dp[left] = arr[i]; + } + } + + // * 3. 출력(전체 길이에서 LIS 길이를 뺀 값을 출력) + System.out.println(n - p); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + dp = new int[n]; + arr = new int[n]; + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(br.readLine()); + } + } +} From 8a8a28e0ade45e9fde004f6607fbf50742b2003d Mon Sep 17 00:00:00 2001 From: dongjji Date: Sun, 9 Oct 2022 21:21:01 +0900 Subject: [PATCH 103/163] =?UTF-8?q?[BOJ-9084-JAVA]=20=EB=8F=99=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_9084.java | 107 +++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_9084.java diff --git a/java/BOJ/Gold/V/G5_9084.java b/java/BOJ/Gold/V/G5_9084.java new file mode 100644 index 0000000..a3f2083 --- /dev/null +++ b/java/BOJ/Gold/V/G5_9084.java @@ -0,0 +1,107 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/9084 + * + * ? 제목: 동전 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 우리나라 화폐단위, 특히 동전에는 1원, 5원, 10원, 50원, 100원, 500원이 있다. 이 동전들로는 정수의 금액을 만들 수 있으며 그 방법도 여러 가지가 있을 수 있다. 예를 들어, 30원을 만들기 위해서는 1원짜리 30개 또는 10원짜리 2개와 5원짜리 2개 등의 방법이 가능하다. + * 동전의 종류가 주어질 때에 주어진 금액을 만드는 모든 방법을 세는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 입력의 첫 줄에는 테스트 케이스의 개수 T(1 ≤ T ≤ 10)가 주어진다. 각 테스트 케이스의 첫 번째 줄에는 동전의 가지 수 N(1 ≤ N ≤ 20)이 주어지고 두 번째 줄에는 N가지 동전의 각 금액이 오름차순으로 정렬되어 주어진다. 각 금액은 정수로서 1원부터 10000원까지 있을 수 있으며 공백으로 구분된다. 세 번째 줄에는 주어진 N가지 동전으로 만들어야 할 금액 M(1 ≤ M ≤ 10000)이 주어진다. + * 편의를 위해 방법의 수는 231 - 1 보다 작고, 같은 동전이 여러 번 주어지는 경우는 없다. + * + * 3 -> t + * 2 -> n + * 1 2 -> arr[0], ... , arr[n-1] + * 1000 -> m + * 3 -> n + * 1 5 10 -> arr[0], ... , arr[n-1] + * 100 -> m + * 2 -> n + * 5 7 -> arr[0], ... , arr[n-1] + * 22 -> m + * + * ? 출력 + * 각 테스트 케이스에 대해 입력으로 주어지는 N가지 동전으로 금액 M을 만드는 모든 방법의 수를 한 줄에 하나씩 출력한다. + * + * 501 + * 121 + * 1 + * + * ? 채점 결과 + * * 시간: 0.088초 + * * 메모리: 12MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.V; + +import java.io.*; +import java.util.StringTokenizer; + +public class G5_9084 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[] arr; + + // * 초기 설정 + static int[][] dp; + + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); // 테스트 케이스 개수 + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < t; i++) { + input(); // * 1. 입력 받기 + + // * 2. 처음으로 나오는 동전의 Start Case 설정 + for (int j = 1; j <= m; j++) { + dp[0][j] = j % arr[0] == 0 ? 1 : 0; + } + + // * 3. 두번째 동전부터 DP + for (int j = 1; j < n; j++) { + int coin = arr[j]; + + dp[j][0] = 1; + for (int k = 1; k <= m; k++) { + dp[j][k] = dp[j-1][k]; // 이전 동전까지만 사용해서 나타낼 수 있는 경우를 먼저 저장 + + if (k >= coin) { + dp[j][k] = dp[j-1][k] + dp[j][k-coin]; + } + } + } + + sb.append(dp[n-1][m] + "\n"); + } + + // * 4. 출력 + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + 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()); + } + + m = Integer.parseInt(br.readLine()); + + dp = new int[n][m+1]; + } +} From 4d3383af9003f827b56e99fe601fb98b88e6425c Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Mon, 10 Oct 2022 13:35:26 +0900 Subject: [PATCH 104/163] =?UTF-8?q?[BOJ-16398-JAVA]=20=ED=96=89=EC=84=B1?= =?UTF-8?q?=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_16398.java | 128 +++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_16398.java diff --git a/java/BOJ/Gold/IV/G4_16398.java b/java/BOJ/Gold/IV/G4_16398.java new file mode 100644 index 0000000..b48621e --- /dev/null +++ b/java/BOJ/Gold/IV/G4_16398.java @@ -0,0 +1,128 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16398 + * + * ? 제목: 행성 연결 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 홍익 제국의 중심은 행성 T이다. 제국의 황제 윤석이는 행성 T에서 제국을 효과적으로 통치하기 위해서, N개의 행성 간에 플로우를 설치하려고 한다. + * 두 행성 간에 플로우를 설치하면 제국의 함선과 무역선들은 한 행성에서 다른 행성으로 무시할 수 있을 만큼 짧은 시간만에 이동할 수 있다. 하지만, 치안을 유지하기 위해서 플로우 내에 제국군을 주둔시켜야 한다. + * 모든 행성 간에 플로우를 설치하고 플로우 내에 제국군을 주둔하면, 제국의 제정이 악화되기 때문에 황제 윤석이는 제국의 모든 행성을 연결하면서 플로우 관리 비용을 최소한으로 하려 한다. + * N개의 행성은 정수 1,…,N으로 표시하고, 행성 i와 행성 j사이의 플로우 관리비용은 Cij이며, i = j인 경우 항상 0이다. + * 제국의 참모인 당신은 제국의 황제 윤석이를 도와 제국 내 모든 행성을 연결하고, 그 유지비용을 최소화하자. 이때 플로우의 설치비용은 무시하기로 한다. + * + * ? 입력 & 파싱 + * 입력으로 첫 줄에 행성의 수 N (1 ≤ N ≤ 1000)이 주어진다. + * 두 번째 줄부터 N+1줄까지 각 행성간의 플로우 관리 비용이 N x N 행렬 (Cij), (1 ≤ i, j ≤ N, 1 ≤ Cij ≤ 100,000,000, Cij = Cji, Cii = 0) 로 주어진다. + * + * 3 -> n + * 0 2 3 -> arr[0][0] ~ arr[0][n-1] + * 2 0 1 + * 3 1 0 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 모든 행성을 연결했을 때, 최소 플로우의 관리비용을 출력한다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 1.556초 + * * 메모리: 185MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +import java.io.*; +import java.util.PriorityQueue; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G4_16398 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[][] arr; + + // * 초기 설정 + static long cost; + static boolean[] visited; + static int[] parent; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + prim(); // * 2. 최소 스패닝 트리(프림 알고리즘) + bw.write(String.valueOf(cost)); // * 3. 출력 + + br.close(); + bw.flush(); + bw.close(); + } + + // 최소 스패닝 트리(프림 알고리즘) + public static void prim() { + int count = 1; + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[2] - b[2]); + for (int i = 1; i < n; i++) { + pq.add(new int[] {0, i, arr[0][i]}); + } + + while (!pq.isEmpty() || count < n) { + int[] cur = pq.poll(); + + if (findParent(cur[0]) != findParent(cur[1])) { + count++; + cost += cur[2]; + union(cur[0], cur[1]); + + for (int i = 0; i < n; i++) { + if (i == cur[1]) { + continue; + } + + pq.add(new int[] {cur[1], i, arr[cur[1]][i]}); + } + } + } + + } + + // UNION_FIND + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + public static void union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + parent = IntStream.range(0, n).toArray(); + arr = new int[n][n]; + visited = new boolean[n]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j= 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 47b9fafd353cb32658555ef02e8b97fe2b4f33be Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 11 Oct 2022 15:22:48 +0900 Subject: [PATCH 105/163] =?UTF-8?q?[BOJ-2533-JAVA]=20=EC=82=AC=ED=9A=8C?= =?UTF-8?q?=EB=A7=9D=20=EC=84=9C=EB=B9=84=EC=8A=A4(SNS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_2533.java | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_2533.java diff --git a/java/BOJ/Gold/III/G3_2533.java b/java/BOJ/Gold/III/G3_2533.java new file mode 100644 index 0000000..39d39d3 --- /dev/null +++ b/java/BOJ/Gold/III/G3_2533.java @@ -0,0 +1,102 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2533 + * + * ? 제목: 사회망 서비스(SNS) + * ? 시간 제한: 3초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 페이스북, 트위터, 카카오톡과 같은 사회망 서비스(SNS)가 널리 사용됨에 따라, 사회망을 통하여 사람들이 어떻게 새로운 아이디어를 받아들이게 되는가를 이해하는 문제가 중요해졌다. 사회망에서 사람들의 친구 관계는 그래프로 표현할 수 있는데, 이 그래프에서 사람은 정점으로 표현되고, 두 정점을 잇는 에지는 두 정점으로 표현되는 두 사람이 서로 친구 관계임을 표현한다. + * 예를 들어, 철수와 영희, 철수와 만수, 영희와 순희가 서로 친구 관계라면 이를 표현하는 친구 관계 그래프는 다음과 같다. + * 친구 관계 그래프를 이용하면 사회망 서비스에서 어떤 새로운 아이디어가 전파되는 과정을 이해하는데 도움을 줄 수 있다. 어떤 새로운 아이디어를 먼저 받아들인 사람을 얼리 아답터(early adaptor)라고 하는데, 사회망 서비스에 속한 사람들은 얼리 아답터이거나 얼리 아답터가 아니다. 얼리 아답터가 아닌 사람들은 자신의 모든 친구들이 얼리 아답터일 때만 이 아이디어를 받아들인다. + * 어떤 아이디어를 사회망 서비스에서 퍼뜨리고자 할 때, 가능한 한 최소의 수의 얼리 아답터를 확보하여 모든 사람이 이 아이디어를 받아들이게 하는 문제는 매우 중요하다. + * 일반적인 그래프에서 이 문제를 푸는 것이 매우 어렵다는 것이 알려져 있기 때문에, 친구 관계 그래프가 트리인 경우, 즉 모든 두 정점 사이에 이들을 잇는 경로가 존재하면서 사이클이 존재하지 않는 경우만 고려한다. + * 예를 들어, 8명의 사람으로 이루어진 다음 친구 관계 트리를 생각해보자. 2, 3, 4번 노드가 표현하는 사람들이 얼리 아답터라면, 얼리 아답터가 아닌 사람들은 자신의 모든 친구가 얼리 아답터이기 때문에 새로운 아이디어를 받아들인다. + * 친구 관계 트리가 주어졌을 때, 모든 개인이 새로운 아이디어를 수용하기 위하여 필요한 최소 얼리 어답터의 수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫 번째 줄에는 친구 관계 트리의 정점 개수 N이 주어진다. 단, 2 ≤ N ≤ 1,000,000이며, 각 정점은 1부터 N까지 일련번호로 표현된다. 두 번째 줄부터 N-1개의 줄에는 각 줄마다 친구 관계 트리의 에지 (u, v)를 나타내는 두 정수 u와 v가 하나의 빈칸을 사이에 두고 주어진다. + * + * 8 -> n + * 1 2 -> a b + * 1 3 -> a b + * 1 4 -> a b + * 2 5 -> a b + * 2 6 -> a b + * 4 7 -> a b + * 4 8 -> a b + * + * ? 출력 + * 주어진 친구 관계 그래프에서 아이디어를 전파하는데 필요한 얼리 아답터의 최소 수를 하나의 정수로 출력한다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 2.168초 + * * 메모리: 427MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +public class G3_2533 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + // * 파싱 + static int n; + static ArrayList[] adj; + + // * 초기 설정 + static int[][] dp; + static boolean[] visit; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + findMinAdaptor(1); // * 2. 트리 DP + System.out.println(Math.min(dp[1][0], dp[1][1])); // * 3. 출력 + + br.close(); + } + + public static void findMinAdaptor(int node) { + visit[node] = true; + dp[node][0] = 1; + + for (int child : adj[node]) { + if (visit[child]) { + continue; + } + + findMinAdaptor(child); + dp[node][0]+=Math.min(dp[child][1],dp[child][0]); + dp[node][1]+=dp[child][0]; + } + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + visit = new boolean[n+1]; + adj = new ArrayList[n+1]; + dp = new int[n+1][2]; + + for (int i = 1; i <= n; i++) { + adj[i] = new ArrayList<>(); + } + + for (int i = 1; i < n; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + adj[a].add(b); + adj[b].add(a); + } + } +} From ed538feb376bb72f6dac78190a479df39be14342 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 12 Oct 2022 12:18:33 +0900 Subject: [PATCH 106/163] =?UTF-8?q?[BOJ-14567-JAVA]=20=EC=84=A0=EC=88=98?= =?UTF-8?q?=EA=B3=BC=EB=AA=A9(Prerequisite)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_14567.java | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_14567.java diff --git a/java/BOJ/Gold/V/G5_14567.java b/java/BOJ/Gold/V/G5_14567.java new file mode 100644 index 0000000..c6563d5 --- /dev/null +++ b/java/BOJ/Gold/V/G5_14567.java @@ -0,0 +1,118 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14567 + * + * ? 제목: 선수과목(Prerequisite) + * ? 시간 제한: 5초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다. + * 한 학기에 들을 수 있는 과목 수에는 제한이 없다. + * 모든 과목은 매 학기 항상 개설된다. + * 모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라. + * + * ? 입력 & 파싱 + * 첫 번째 줄에 과목의 수 N(1 ≤ N ≤ 1000)과 선수 조건의 수 M(0 ≤ M ≤ 500000)이 주어진다. 선수과목 조건은 M개의 줄에 걸쳐 한 줄에 정수 A B 형태로 주어진다. A번 과목이 B번 과목의 선수과목이다. A < B인 입력만 주어진다. (1 ≤ A < B ≤ N) + * + * 3 2 -> n m + * 2 3 -> a b + * 1 2 -> a b + * + * ? 출력 + * 1번 과목부터 N번 과목까지 차례대로 최소 몇 학기에 이수할 수 있는지를 한 줄에 공백으로 구분하여 출력한다. + * + * 1 2 3 + * + * ? 채점 결과 + * * 시간: 0.584초 + * * 메모리: 130MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G5_14567 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static ArrayList[] adj; + + // * 초기 설정 + static boolean[] visit; + static int[] degree, sequence; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. 위상 정렬(BFS) + Queue queue = new LinkedList<>(); + for (int i = 1; i <= n; i++) { + if (degree[i] == 0) { + queue.add(new int[] {i, 1}); + visit[i] = true; + } + } + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + sequence[cur[0]] = cur[1]; + + for (int next: adj[cur[0]]) { + if (visit[next]) { + continue; + } + + if (--degree[next] == 0) { + queue.add(new int[] {next, cur[1]+1}); + visit[next] = true; + } + } + } + + // * 3. 출력 + StringBuffer sb = new StringBuffer(); + for (int i = 1; i <= n; i++) { + sb.append(sequence[i] + " "); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + degree = new int[n+1]; + sequence = new int[n+1]; + visit = new boolean[n+1]; + adj = new ArrayList[n+1]; + for (int i = 1; i <= n; i++) { + adj[i] = new ArrayList<>(); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + degree[b]++; + adj[a].add(b); + } + } +} From d4c886071e410fd900f8b8b60a4ce3c50292bf1a Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 13 Oct 2022 17:05:39 +0900 Subject: [PATCH 107/163] =?UTF-8?q?[BOJ-5582-JAVA]=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EB=AC=B8=EC=9E=90=EC=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_5582.java | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_5582.java diff --git a/java/BOJ/Gold/V/G5_5582.java b/java/BOJ/Gold/V/G5_5582.java new file mode 100644 index 0000000..ae3afec --- /dev/null +++ b/java/BOJ/Gold/V/G5_5582.java @@ -0,0 +1,74 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/5582 + * + * ? 제목: 공통 부분 문자열 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 두 문자열이 주어졌을 때, 두 문자열에 모두 포함된 가장 긴 공통 부분 문자열을 찾는 프로그램을 작성하시오. + * 어떤 문자열 s의 부분 문자열 t란, s에 t가 연속으로 나타나는 것을 말한다. 예를 들어, 문자열 ABRACADABRA의 부분 문자열은 ABRA, RAC, D, ACADABRA, ABRACADABRA, 빈 문자열 등이다. 하지만, ABRC, RAA, BA, K는 부분 문자열이 아니다. + * 두 문자열 ABRACADABRA와 ECADADABRBCRDARA의 공통 부분 문자열은 CA, CADA, ADABR, 빈 문자열 등이 있다. 이 중에서 가장 긴 공통 부분 문자열은 ADABR이며, 길이는 5이다. 또, 두 문자열이 UPWJCIRUCAXIIRGL와 SBQNYBSBZDFNEV인 경우에는 가장 긴 공통 부분 문자열은 빈 문자열이다. + * + * ? 입력 & 파싱 + * 첫째 줄과 둘째 줄에 문자열이 주어진다. 문자열은 대문자로 구성되어 있으며, 길이는 1 이상 4000 이하이다. + * + * ABRACADABRA -> str1 + * ECADADABRBCRDARA -> str2 + * + * ? 출력 + * 첫째 줄에 두 문자열에 모두 포함 된 부분 문자열 중 가장 긴 것의 길이를 출력한다. + * + * 5 + * + * ? 채점 결과 + * * 시간: 0.184초 + * * 메모리: 74MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.V; + +import java.io.*; +import java.util.Arrays; + +public class G5_5582 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + // * 파싱 + static char[] str1, str2; + + // * 초기 설정 + static int max = 0; + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) + for (int i = 1; i <= str1.length; i++) { + for (int j = 1; j <= str2.length; j++) { + if (str1[i - 1] == str2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + max = Math.max(max, dp[i][j]); + } + } + } + + // * 3. 출력 + bw.write(String.valueOf(max)); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + str1 = br.readLine().toCharArray(); + str2 = br.readLine().toCharArray(); + dp = new int[str1.length + 1][str2.length + 1]; + } +} From 7c5277fb5a2deccad0a8e311b7da3270b9621e26 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 14 Oct 2022 13:05:41 +0900 Subject: [PATCH 108/163] [BOJ-16929-JAVA] Two Dots --- java/BOJ/Gold/IV/G4_16929.java | 126 +++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_16929.java diff --git a/java/BOJ/Gold/IV/G4_16929.java b/java/BOJ/Gold/IV/G4_16929.java new file mode 100644 index 0000000..72b09fd --- /dev/null +++ b/java/BOJ/Gold/IV/G4_16929.java @@ -0,0 +1,126 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16929 + * + * ? 제목: Two Dots + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * Two Dots는 Playdots, Inc.에서 만든 게임이다. 게임의 기초 단계는 크기가 N×M인 게임판 위에서 진행된다. + * 각각의 칸은 색이 칠해진 공이 하나씩 있다. 이 게임의 핵심은 같은 색으로 이루어진 사이클을 찾는 것이다. + * 다음은 위의 게임판에서 만들 수 있는 사이클의 예시이다. + * 점 k개 d1, d2, ..., dk로 이루어진 사이클의 정의는 아래와 같다. + * + * 모든 k개의 점은 서로 다르다. + * k는 4보다 크거나 같다. + * 모든 점의 색은 같다. + * 모든 1 ≤ i ≤ k-1에 대해서, di와 di+1은 인접하다. 또, dk와 d1도 인접해야 한다. 두 점이 인접하다는 것은 각각의 점이 들어있는 칸이 변을 공유한다는 의미이다. + * 게임판의 상태가 주어졌을 때, 사이클이 존재하는지 아닌지 구해보자. + * + * ? 입력 & 파싱 + * 첫째 줄에 게임판의 크기 N, M이 주어진다. 둘째 줄부터 N개의 줄에 게임판의 상태가 주어진다. 게임판은 모두 점으로 가득차 있고, 게임판의 상태는 점의 색을 의미한다. 점의 색은 알파벳 대문자 한 글자이다. + * + * 3 4 -> n m + * AAAA -> arr[0][0] ~ arr[0][m-1] + * ABCA + * AAAA -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 사이클이 존재하는 경우에는 "Yes", 없는 경우에는 "No"를 출력한다. + * + * Yes + * + * ? 제한 + * + * 2 ≤ N, M ≤ 50 + * + * ? 채점 결과 + * * 시간: 0.076초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +import java.io.*; +import java.util.StringTokenizer; + +public class G4_16929 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static char[][] arr; + + // * 초기 설정 + static boolean hasCycle = false; + static boolean[][] visit; + + // * 상하좌우 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DFS + dfsLoop: + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (!visit[i][j]) { + visit[i][j] = true; + dfs(i, j, i, j); + } + + if (hasCycle) { + break dfsLoop; + } + } + } + + // * 3. 출력 + bw.write(hasCycle ? "Yes" : "No"); + + br.close(); + bw.flush(); + bw.close(); + } + + // DFS + public static void dfs(int x, int y, int bx, int by) { + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m || (nx == bx && ny == by)) { + continue; + } + + if (arr[nx][ny] == arr[x][y]) { + if (visit[nx][ny]) { + hasCycle = true; + return; + } + + visit[nx][ny] = true; + dfs(nx, ny, x, y); + } + } + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + visit = new boolean[n][m]; + arr = new char[n][m]; + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + } +} From 3b54d218d7c9cf4619142e242826d8383dbe5411 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 15 Oct 2022 14:52:38 +0900 Subject: [PATCH 109/163] =?UTF-8?q?[BOJ-2629-JAVA]=20=EC=96=91=ED=8C=94?= =?UTF-8?q?=EC=A0=80=EC=9A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_2629.java | 159 +++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_2629.java diff --git a/java/BOJ/Gold/III/G3_2629.java b/java/BOJ/Gold/III/G3_2629.java new file mode 100644 index 0000000..5acdbee --- /dev/null +++ b/java/BOJ/Gold/III/G3_2629.java @@ -0,0 +1,159 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2629 + * + * ? 제목: 양팔저울 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 양팔 저울과 몇 개의 추가 주어졌을 때, 이를 이용하여 입력으로 주어진 구슬의 무게를 확인할 수 있는지를 결정하려고 한다. + * 무게가 각각 1g과 4g인 두 개의 추가 있을 경우, 주어진 구슬과 1g 추 하나를 양팔 저울의 양쪽에 각각 올려놓아 수평을 이루면 구슬의 무게는 1g이다. 또 다른 구슬이 4g인지를 확인하려면 1g 추 대신 4g 추를 올려놓으면 된다. + * 구슬이 3g인 경우 아래 <그림 1>과 같이 구슬과 추를 올려놓으면 양팔 저울이 수평을 이루게 된다. 따라서 각각 1g과 4g인 추가 하나씩 있을 경우 주어진 구슬이 3g인지도 확인해 볼 수 있다. + * <그림 1> 구슬이 3g인지 확인하는 방법 ($\boxed{1}$은 1g인 추, $\boxed{4}$는 4g인 추, ●은 무게를 확인할 구슬) + * <그림 2>와 같은 방법을 사용하면 구슬이 5g인지도 확인할 수 있다. 구슬이 2g이면 주어진 추를 가지고는 확인할 수 없다. + * 추들의 무게와 확인할 구슬들의 무게가 입력되었을 때, 주어진 추만을 사용하여 구슬의 무게를 확인 할 수 있는지를 결정하는 프로그램을 작성하시오. + * <그림 2> 구슬이 5g인지 확인하는 방법 + * + * ? 입력 & 파싱 + * 첫째 줄에는 추의 개수가 자연수로 주어진다. 추의 개수는 30 이하이다. 둘째 줄에는 추의 무게들이 자연수로 가벼운 것부터 차례로 주어진다. 같은 무게의 추가 여러 개 있을 수도 있다. 추의 무게는 500g이하이며, 입력되는 무게들 사이에는 빈칸이 하나씩 있 다. 세 번째 줄에는 무게를 확인하고자 하는 구슬들의 개수가 주어진다. 확인할 구슬의 개수는 7이하이다. 네 번째 줄에는 확인하고자 하는 구슬들의 무게가 자연수로 주어지며, 입력되는 무게들 사이에는 빈 칸이 하나씩 있다. 확인하고자 하는 구슬의 무게는 40,000보다 작거나 같은 자연수이다. + * + * 2 -> n + * 1 4 -> chu[0] ~ chu[n-1] + * 2 -> m + * 3 2 -> beads.get(0) ~ beads.get(m-1) + * + * ? 출력 + * 주어진 각 구슬의 무게에 대하여 확인이 가능하면 Y, 아니면 N 을 차례로 출력한다. 출력은 한 개의 줄로 이루어지며, 각 구슬에 대한 답 사이에는 빈칸을 하나씩 둔다. + * + * Y N + * + * ? 채점 결과 + * * 시간: 0.152초 + * * 메모리: 32MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +public class G3_2629 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, m; + static int[] chu; + static ArrayList beads; + + // * 초기 설정 + static boolean[][] visit; + static ArrayList[][] dp; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation) - Start Case 설정 + dp[0][0].add(chu[0]); + visit[0][chu[0]] = true; + + for (int i = 1; i < n; i++) { + if (!visit[0][chu[i]]) { + visit[0][chu[i]] = true; + dp[0][i].add(chu[i]); + } + + int next1 = chu[0] + chu[i]; + int next2 = Math.abs(chu[0] - chu[i]); + + if (!visit[i][next1]) { + visit[i][next1] = true; + dp[0][i].add(next1); + } + + if (!visit[i][next2]) { + visit[i][next2] = true; + dp[0][i].add(next2); + } + } + + // * 3. DP(Tabulation: Bottom-Up) + for (int i = 1; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + dp[i][j] = dp[i-1][j]; + continue; + } + + for (int bead : dp[i-1][j]) { + dp[i][j].add(bead); + + int next1 = chu[i] + bead; + if (!visit[j][next1]) { + visit[j][next1] = true; + dp[i][j].add(next1); + } + + int next2 = Math.abs(chu[i] - bead); + if (!visit[j][next2]) { + visit[j][next2] = true; + dp[i][j].add(next2); + } + } + } + } + + // * 4. 출력 + StringBuffer sb = new StringBuffer(); + for (int bead : beads) { + boolean able = false; + for (int i = 0; i < n; i++) { + if (visit[i][bead]) { + able = true; + break; + } + } + + if (able) { + sb.append("Y "); + } else { + sb.append("N "); + } + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + chu = new int[n]; + visit = new boolean[n][400001]; + dp = new ArrayList[n][n]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + dp[i][j] = new ArrayList<>(); + } + } + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + chu[i] = Integer.parseInt(st.nextToken()); + } + + beads = new ArrayList<>(); + m = Integer.parseInt(br.readLine()); + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < m; i++) { + beads.add(Integer.parseInt(st.nextToken())); + } + } +} From a0537538f43860630847beb479c52e17846d2185 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 16 Oct 2022 13:37:16 +0900 Subject: [PATCH 110/163] =?UTF-8?q?[BOJ-15971-JAVA]=20=EB=91=90=20?= =?UTF-8?q?=EB=A1=9C=EB=B4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G4_15971.java | 143 ++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 java/BOJ/Gold/V/G4_15971.java diff --git a/java/BOJ/Gold/V/G4_15971.java b/java/BOJ/Gold/V/G4_15971.java new file mode 100644 index 0000000..2d52621 --- /dev/null +++ b/java/BOJ/Gold/V/G4_15971.java @@ -0,0 +1,143 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/15971 + * + * ? 제목: 두 로봇 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 2018년 강원도에서 새로운 동굴이 발견되었다. 이 동굴에는 총 N개의 넓은 방이 존재하며 좁은 통로로 서로 연결되어 있는 것으로 밝혀졌다. N개의 방은 1번부터 N번까지의 번호를 붙여 1번 방, 2번 방, …, N번 방으로 부른다. 통로는 정확히 N-1개가 발견되었는데, 각각 서로 다른 두 방 사이를 연결시켜 주며 중간에 다른 통로와 이어지는 경우는 없다고 한다. 또한 이 통로들을 이용하여 임의의 두 방 사이를 이동하는 것이 가능하며, 임의의 두 방 사이를 이동할 때 같은 통로를 두 번 이상 지나지 않는 경로는 유일한 것으로 밝혀졌다. + * 새로 발견된 동굴을 조사하기 위해 동굴 탐사 로봇 두 대를 이용하기로 하였다. 두 로봇은 어떤 시점이 되면 각자가 획득한 정보를 공유하기 위해 통신을 해야 한다. 두 로봇이 서로 통신을 하기 위해서는 동굴 내의 같은 통로 위에 위치해야만 한다. 참고로 임의의 통로의 양 끝에 위치한 두 방들도 그 통로 위에 위치해 있다고 간주한다. + * <그림 1> 동굴 내부를 간략히 표현한 그림 + * <그림 1>은 방이 9개인 동굴 내부를 간략하게 나타낸 예이다. <그림 1>에서 방은 원으로 표현되어 있으며 원 안의 수는 방 번호이다. 8개의 통로는 두 원 사이의 선분으로 표시되어 있으며 그 위의 정수 값이 통로의 길이이다. 예를 들어, 5번 방과 9번 방 사이에 길이가 6 인 통로가 있음을 알 수 있다. 만약 두 로봇이 1번 방과 9번 방에 위치해 있다면, 각각 2번 방과 5번 방으로 이동한 후 통신할 수 있으며 이때 이동한 거리의 합은 14로 최소이다. + * 동굴 내의 통로에 대한 정보와 두 로봇의 현재 위치가 입력으로 주어질 때, 서로 통신하기 위해 이동해야 하는 거리의 합의 최솟값을 계산하는 프로그램을 작성하시오. + * 동굴의 각 통로는 양 끝에 위치한 두 방의 번호와 그 길이로 주어진다. 두 로봇의 위치는 방 번호로 주어진다. + * + * ? 입력 & 파싱 + * 표준 입력으로 동굴의 방의 개수 N과 두 로봇이 위치한 방의 번호가 세 개의 양의 정수로 공백으로 분리되어 첫 줄에 주어진다. 이후 동굴의 통로 N-1개가 한 줄에 하나씩 주어진다. 각 통로는 세 개의 양의 정수로 공백으로 분리되어 한 줄에 주어지며, 앞 두 정수는 통로의 양 끝에 위치한 방의 번호를, 세 번째 정수는 그 통로의 길이를 의미한다. + * + * 5 1 5 -> n s e + * 1 2 1 -> a b c + * 2 3 2 -> a b c + * 3 4 3 -> a b c + * 4 5 4 -> a b c + * + * ? 출력 + * 표준 출력으로 두 로봇이 서로 통신하기 위해 현재 위치에서 이동해야 하는 거리의 합의 최솟값을 정수로 출력한다. + * + * 6 + * + * ? 제한 + * 모든 서브태스크에서 1 ≤ N ≤ 100,000이며, 통로의 길이는 1,000을 넘지 않는다. + * + * ? 채점 결과 + * * 시간: 0.588초 + * * 메모리: 83MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G4_15971 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, s, e; + static ArrayList[] adj; + + // * 초기 설정 + static int totalLength = 0; + static int maxLength = 0; + static boolean[] visit; // 방문 리스트 + static int[] before; // 방문하기 전에 지나온 노드의 번호 + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + bfs(); // * 2. BFS 수행 + 경로 저장 + findWay(); // * 3. 경로를 역으로 돌아가면서 total 길이와 max 길이를 구함 + bw.write(String.valueOf(totalLength - maxLength)); // * 4. 출력 + + br.close(); + bw.flush(); + bw.close(); + } + + // BFS + public static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {s, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == e) { + break; + } + + for (int[] next: adj[cur[0]]) { + if (!visit[next[0]]) { + visit[next[0]] = true; + before[next[0]] = cur[0]; + queue.add(new int[] {next[0], cur[1] + next[1]}); + } + } + } + } + + // 경로 찾기 + public static void findWay() { + Queue queue = new LinkedList<>(); + queue.add(e); + + while (!queue.isEmpty()) { + int cur = queue.poll(); + + if (cur == s) { + break; + } + + for (int[] next : adj[cur]) { + if (next[0] == before[cur]) { + queue.add(next[0]); + maxLength = Math.max(maxLength, next[1]); + totalLength += next[1]; + } + } + } + } + + // 입력 받기 + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + s = Integer.parseInt(st.nextToken()); + e = Integer.parseInt(st.nextToken()); + + adj = new ArrayList[n+1]; + for (int i = 1; i <= n; i++) { + adj[i] = new ArrayList<>(); + } + + for (int i = 1; i <= n-1; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + adj[a].add(new int[] {b, c}); + adj[b].add(new int[] {a, c}); + } + + visit = new boolean[n+1]; + before = new int[n+1]; + } +} From 86abffad0bb0d531e0ed3dad01e411c8f67eff86 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Mon, 17 Oct 2022 16:13:47 +0900 Subject: [PATCH 111/163] =?UTF-8?q?[BOJ-13398-JAVA]=20=EC=97=B0=EC=86=8D?= =?UTF-8?q?=ED=95=A9=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_13398.java | 92 +++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_13398.java diff --git a/java/BOJ/Gold/V/G5_13398.java b/java/BOJ/Gold/V/G5_13398.java new file mode 100644 index 0000000..52e8651 --- /dev/null +++ b/java/BOJ/Gold/V/G5_13398.java @@ -0,0 +1,92 @@ +/** + * ? 문제 출처: 백준 온라인 져지 + * ? https://www.acmicpc.net/problem/13398 + * + * ? 제목: 연속합 2 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * n개의 정수로 이루어진 임의의 수열이 주어진다. 우리는 이 중 연속된 몇 개의 수를 선택해서 구할 수 있는 합 중 가장 큰 합을 구하려고 한다. 단, 수는 한 개 이상 선택해야 한다. 또, 수열에서 수를 하나 제거할 수 있다. (제거하지 않아도 된다) + * 예를 들어서 10, -4, 3, 1, 5, 6, -35, 12, 21, -1 이라는 수열이 주어졌다고 하자. 여기서 수를 제거하지 않았을 때의 정답은 12+21인 33이 정답이 된다. + * 만약, -35를 제거한다면, 수열은 10, -4, 3, 1, 5, 6, 12, 21, -1이 되고, 여기서 정답은 10-4+3+1+5+6+12+21인 54가 된다. + * + * ? 입력 & 파싱 + * 첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다. + * + * 10 -> n + * 10 -4 3 1 5 6 -35 12 21 -1 -> arr[0] ~ arr[n-1] + * + * ? 출력 + * 첫째 줄에 답을 출력한다. + * + * 54 + * + * ? 채점 결과 + * * 시간: 0.224초 + * * 메모리: 22MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.V; + +import java.io.*; +import java.util.StringTokenizer; + +public class G5_13398 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static int[] arr; + + // * 초기 설정 + static int answer; + static int[] dp1, dp2; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. DP(Tabulation: Bottom-Up) + // * 왼쪽 -> 오른쪽 연속합의 최댓값 dp + answer = arr[0]; + dp1[0] = arr[0]; + for (int i = 1; i < n; i++) { + dp1[i] = Math.max(dp1[i - 1] + arr[i], arr[i]); + answer = Math.max(answer, dp1[i]); // 숫자를 제거하지 않는 경우의 max 값 업데이트 + } + + // * 오른쪽 -> 왼쪽 연속합의 최댓값 dp + dp2[n-1] = arr[n-1]; + for (int i = n - 2; i >= 0; i--) { + dp2[i] = Math.max(dp2[i + 1] + arr[i], arr[i]); + } + + // * 숫자를 제거하는 경우에 왼쪽 -> i <- 오른쪽 연속합의 합의 최댓값 업데이트 + for (int i = 1; i < n-1; i++) { + answer = Math.max(answer, dp1[i-1] + dp2[i+1]); + } + + // * 3. 출력 + bw.write(String.valueOf(answer)); + + br.close(); + bw.flush(); + bw.close(); + } + + // 입력 받기 + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new int[n]; + dp1 = new int[n]; + dp2 = new int[n]; + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + } + } +} From 3e129ff89935e478d8a6b0ff459470b2eb3d50d1 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 18 Oct 2022 13:45:58 +0900 Subject: [PATCH 112/163] [BOJ-10216-JAVA] Count Circle Groups --- java/BOJ/Gold/V/G5_10216.java | 130 ++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_10216.java diff --git a/java/BOJ/Gold/V/G5_10216.java b/java/BOJ/Gold/V/G5_10216.java new file mode 100644 index 0000000..39ef485 --- /dev/null +++ b/java/BOJ/Gold/V/G5_10216.java @@ -0,0 +1,130 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/10216 + * + * ? 문제: Count Circle Groups + * ? 시간 제한: 8초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 백준이는 국방의 의무를 수행하기 위해 떠났다. 혹독한 훈련을 무사히 마치고 나서, 정말 잘 생겼고 코딩도 잘하는 백준은 그 특기를 살려 적군의 진영을 수학적으로 분석하는 일을 맡게 되었다. + * 2차원 평면 위의 N곳에 적군의 진영이 설치되어 있다. 각 적군의 진영들은 진영마다 하나의 통신탑을 설치해, i번째 적군의 통신탑은 설치 위치로부터 Ri 이내 거리에 포함되는 모든 지역을 자신의 통신영역 Ai로 가지게 된다. 만약 임의의 통신영역 Ai와 Aj가 닿거나 겹치는 부분이 있다면 진영 i와 진영 j는 직접적으로 통신이 가능하다. 물론 직접적으로 통신이 가능하지 않더라도, 임의의 지역 i와 j가 중간에 몇 개의 직접통신을 거쳐서 최종적으로 통신이 가능하다면 i와 j는 상호간에 통신이 가능한 것으로 본다. + * 적들은 영리해서, 상호간에 통신이 가능한 부대끼리는 결집력있는 한 그룹처럼 행동한다. 백준은 이러한 그룹의 개수를 알아내 아군의 전략지침에 도움을 주고자 한다. 군대에 가서도 코딩하는 불쌍한 백준을 위해 적군의 통신망 분석을 도와주자! + * + * ? 입력 & 파싱 + * 입력 파일의 첫 번째 줄에 테스트 케이스의 수를 의미하는 자연수 T가 주어진다. 그 다음에는 T개의 테스트 케이스가 주어진다. + * 각각의 테스트 케이스에 대해서 적군 진영의 숫자 N (1 ≤ N ≤ 3,000)이 주어진다. 이어서 N줄에 걸쳐 적군 진영의 좌표 x, y (0 ≤ x, y ≤ 5,000), 그리고 해당 진영의 R (0 ≤ R ≤ 5,000)이 주어진다. 주어지는 수는 모두 정수이다. + * + * 2 -> test + * 2 -> n + * 0 0 1 -> a b r + * 1 0 1 -> a b r + * 3 -> ... + * 0 0 1 + * 2 0 1 + * 10 0 5 + * + * ? 출력 + * 각 테스트 케이스에 대해서 한 줄에 걸쳐 적군 진영의 그룹 개수를 출력한다. + * + * 1 + * 2 + * + * ? 채점 결과 + * * 시간: 7.152초 + * * 메모리: 139MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +class Camp { + int num; + int x; + int y; + int r; + + public Camp(int num, int x, int y, int r) { + this.num = num; + this.x = x; + this.y = y; + this.r = r; + } +} + +public class G5_10216 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n; + static ArrayList list; + + // * 초기 설정 + static boolean[] visit; + + public static void main(String[] args) throws IOException { + int test = Integer.parseInt(br.readLine()); + StringBuffer sb = new StringBuffer(); + + for (int t = 0; t < test; t++) { + input(); // * 1. 입력 받기 + + // * 2. DFS + int count = 0; + for (int i = 0; i < n; i++) { + if (!visit[list.get(i).num]) { + count++; + visit[list.get(i).num] = true; + dfs(list.get(i)); + } + } + + sb.append(count + "\n"); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + // DFS + public static void dfs(Camp cur) { + for (int i = 0; i < n; i++) { + Camp next = list.get(i); + + // 통신 범위 내의 있는 진영이면서 방문한 적이 없는 곳에 대하여 재귀 DFS 수행 + if (!visit[next.num] && isConnected(cur, next)) { + visit[next.num] = true; + dfs(next); + } + } + } + + public static boolean isConnected(Camp camp1, Camp camp2) { + return (camp1.r + camp2.r) * (camp1.r + camp2.r) >= (camp1.x - camp2.x) * (camp1.x - camp2.x) + (camp1.y - camp2.y) * (camp1.y - camp2.y); + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + visit = new boolean[n]; + list = new ArrayList<>(); + + int x, y, r; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + x = Integer.parseInt(st.nextToken()); + y = Integer.parseInt(st.nextToken()); + r = Integer.parseInt(st.nextToken()); + + list.add(new Camp(i, x, y, r)); + } + } +} From a1de0066b119ec578c6de1588d057f6fff094536 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 19 Oct 2022 16:54:49 +0900 Subject: [PATCH 113/163] =?UTF-8?q?[BOJ-15486-JAVA]=20=ED=87=B4=EC=82=AC?= =?UTF-8?q?=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_15486.java | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_15486.java diff --git a/java/BOJ/Gold/V/G5_15486.java b/java/BOJ/Gold/V/G5_15486.java new file mode 100644 index 0000000..14bdf92 --- /dev/null +++ b/java/BOJ/Gold/V/G5_15486.java @@ -0,0 +1,47 @@ +/** + * ? 문제 출처; + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G5_15486 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n; + static int[][] arr; + + static int max = 0; + static int[] dp; + + public static void main(String[] args) throws IOException { + input(); + + for (int i = 1; i <= n; i++) { + dp[i] = Math.max(dp[i], dp[i - 1]); + if (i + arr[i][0] <= n + 1) { + dp[i + arr[i][0]] = Math.max(dp[i + arr[i][0]], dp[i] + arr[i][1]); + max = Math.max(dp[i + arr[i][0]], max); + } + } + + System.out.println(max); + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new int[n + 2][2]; + dp = new int[n + 2]; + + for (int i = 1; i <= n; i++) { + st = new StringTokenizer(br.readLine()); + + arr[i][0] = Integer.parseInt(st.nextToken()); + arr[i][1] = Integer.parseInt(st.nextToken()); + } + } +} From e5c4c4c4ddac6730eed98ea416992db686cf91ab Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 19 Oct 2022 17:04:18 +0900 Subject: [PATCH 114/163] =?UTF-8?q?fix:=20[BOJ-15486-JAVA]=20=ED=87=B4?= =?UTF-8?q?=EC=82=AC=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_15486.java | 56 +++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/java/BOJ/Gold/V/G5_15486.java b/java/BOJ/Gold/V/G5_15486.java index 14bdf92..6183957 100644 --- a/java/BOJ/Gold/V/G5_15486.java +++ b/java/BOJ/Gold/V/G5_15486.java @@ -1,5 +1,52 @@ /** - * ? 문제 출처; + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/15486 + * + * ? 제목: 퇴사 2 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 상담원으로 일하고 있는 백준이는 퇴사를 하려고 한다. + * 오늘부터 N+1일째 되는 날 퇴사를 하기 위해서, 남은 N일 동안 최대한 많은 상담을 하려고 한다. + * 백준이는 비서에게 최대한 많은 상담을 잡으라고 부탁을 했고, 비서는 하루에 하나씩 서로 다른 사람의 상담을 잡아놓았다. + * 각각의 상담은 상담을 완료하는데 걸리는 기간 Ti와 상담을 했을 때 받을 수 있는 금액 Pi로 이루어져 있다. + * + * N = 7인 경우에 다음과 같은 상담 일정표를 보자. + * + * 1일 2일 3일 4일 5일 6일 7일 + * Ti 3 5 1 1 2 4 2 + * Pi 10 20 10 20 15 40 200 + * + * 1일에 잡혀있는 상담은 총 3일이 걸리며, 상담했을 때 받을 수 있는 금액은 10이다. 5일에 잡혀있는 상담은 총 2일이 걸리며, 받을 수 있는 금액은 15이다. + * 상담을 하는데 필요한 기간은 1일보다 클 수 있기 때문에, 모든 상담을 할 수는 없다. 예를 들어서 1일에 상담을 하게 되면, 2일, 3일에 있는 상담은 할 수 없게 된다. 2일에 있는 상담을 하게 되면, 3, 4, 5, 6일에 잡혀있는 상담은 할 수 없다. + * 또한, N+1일째에는 회사에 없기 때문에, 6, 7일에 있는 상담을 할 수 없다. + * 퇴사 전에 할 수 있는 상담의 최대 이익은 1일, 4일, 5일에 있는 상담을 하는 것이며, 이때의 이익은 10+20+15=45이다. + * 상담을 적절히 했을 때, 백준이가 얻을 수 있는 최대 수익을 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 N (1 ≤ N ≤ 1,500,000)이 주어진다. + * 둘째 줄부터 N개의 줄에 Ti와 Pi가 공백으로 구분되어서 주어지며, 1일부터 N일까지 순서대로 주어진다. (1 ≤ Ti ≤ 50, 1 ≤ Pi ≤ 1,000) + * + * 7 -> n + * 3 10 -> arr[1][0] arr[1][1] + * 5 20 + * 1 10 + * 1 20 + * 2 15 + * 4 40 + * 2 200 -> arr[n][0] arr[n][1] + * + * ? 출력 + * 첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다. + * + * 45 + * + * ? 채점 결과 + * * 시간: 0.776초 + * * 메모리: 342MB + * * 언어: JAVA8 + * * 시도: 2 */ package Gold.V; @@ -12,15 +59,18 @@ public class G5_15486 { static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static StringTokenizer st; + // * 파싱 static int n; static int[][] arr; + // * 초기 설정 static int max = 0; static int[] dp; public static void main(String[] args) throws IOException { - input(); + input(); // * 1. 입력 받기 + // * 2. DP(Tabulation: Bottom-Up) for (int i = 1; i <= n; i++) { dp[i] = Math.max(dp[i], dp[i - 1]); if (i + arr[i][0] <= n + 1) { @@ -29,9 +79,11 @@ public static void main(String[] args) throws IOException { } } + // * 3. 출력 System.out.println(max); } + // 입력 받기 public static void input() throws IOException { n = Integer.parseInt(br.readLine()); arr = new int[n + 2][2]; From 881700d3a2c5d3a4d11abd1a8c2dd9b7ac40bcd7 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 20 Oct 2022 19:04:18 +0900 Subject: [PATCH 115/163] [BOJ-15591-JAVA] MooTube(Silver) --- java/BOJ/Gold/V/G5_15591.java | 128 ++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_15591.java diff --git a/java/BOJ/Gold/V/G5_15591.java b/java/BOJ/Gold/V/G5_15591.java new file mode 100644 index 0000000..eed6d49 --- /dev/null +++ b/java/BOJ/Gold/V/G5_15591.java @@ -0,0 +1,128 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/15591 + * + * ? 제목: MooTube(Silver) + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 농부 존은 남는 시간에 MooTube라 불리는 동영상 공유 서비스를 만들었다. MooTube에서 농부 존의 소들은 재밌는 동영상들을 서로 공유할 수 있다. 소들은 MooTube에 1부터 N까지 번호가 붙여진 N (1 ≤ N ≤ 5,000)개의 동영상을 이미 올려 놓았다. 하지만, 존은 아직 어떻게 하면 소들이 그들이 좋아할 만한 새 동영상을 찾을 수 있을지 괜찮은 방법을 떠올리지 못했다. + * 농부 존은 모든 MooTube 동영상에 대해 “연관 동영상” 리스트를 만들기로 했다. 이렇게 하면 소들은 지금 보고 있는 동영상과 연관성이 높은 동영상을 추천 받을 수 있을 것이다.* + * 존은 두 동영상이 서로 얼마나 가까운 지를 측정하는 단위인 “USADO”를 만들었다. 존은 N-1개의 동영상 쌍을 골라서 직접 두 쌍의 USADO를 계산했다. 그 다음에 존은 이 동영상들을 네트워크 구조로 바꿔서, 각 동영상을 정점으로 나타내기로 했다. 또 존은 동영상들의 연결 구조를 서로 연결되어 있는 N-1개의 동영상 쌍으로 나타내었다. 좀 더 쉽게 말해서, 존은 N-1개의 동영상 쌍을 골라서 어떤 동영상에서 다른 동영상으로 가는 경로가 반드시 하나 존재하도록 했다. 존은 임의의 두 쌍 사이의 동영상의 USADO를 그 경로의 모든 연결들의 USADO 중 최솟값으로 하기로 했다. + * 존은 어떤 주어진 MooTube 동영상에 대해, 값 K를 정해서 그 동영상과 USADO가 K 이상인 모든 동영상이 추천되도록 할 것이다. 하지만 존은 너무 많은 동영상이 추천되면 소들이 일하는 것이 방해될까 봐 걱정하고 있다! 그래서 그는 K를 적절한 값으로 결정하려고 한다. 농부 존은 어떤 K 값에 대한 추천 동영상의 개수를 묻는 질문 여러 개에 당신이 대답해주기를 바란다. + * + * ? 입력 & 파싱 + * 입력의 첫 번째 줄에는 N과 Q가 주어진다. (1 ≤ Q ≤ 5,000) + * 다음 N-1개의 줄에는 농부 존이 직접 잰 두 동영상 쌍의 USADO가 한 줄에 하나씩 주어진다. 각 줄은 세 정수 pi, qi, ri (1 ≤ pi, qi ≤ N, 1 ≤ ri ≤ 1,000,000,000)를 포함하는데, 이는 동영상 pi와 qi가 USADO ri로 서로 연결되어 있음을 뜻한다. + * 다음 Q개의 줄에는 농부 존의 Q개의 질문이 주어진다. 각 줄은 두 정수 ki와 vi(1 ≤ ki ≤ 1,000,000,000, 1 ≤ vi ≤ N)을 포함하는데, 이는 존의 i번째 질문이 만약 K = ki라면 동영상 vi를 보고 있는 소들에게 몇 개의 동영상이 추천될 지 묻는 것이라는 것을 뜻한다. + * + * 4 3 -> n q + * 1 2 3 -> a b c + * 2 3 2 -> a b c + * 2 4 4 -> a b c + * 1 2 -> k v + * 4 1 -> k v + * 3 1 -> k v + * + * ? 출력 + * Q개의 줄을 출력한다. i번째 줄에는 농부 존의 i번째 질문에 대한 답변이 출력되어야 한다. + * + * 3 + * 0 + * 2 + * + * ? 채점 결과 + * * 시간: 2.276초 + * * 메모리: 302MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G5_15591 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + // * 파싱 + static int n, q; + static ArrayList[] adj; + + // * 초기 설정 + static int[] visit; + + public static void main(String[] args) throws IOException { + input(); // * 1. 입력 받기 + + // * 2. BFS + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < q; i++) { + st = new StringTokenizer(br.readLine()); + int k = Integer.parseInt(st.nextToken()); + int v = Integer.parseInt(st.nextToken()); + + bfs(v); + int count = 0; + for (int j = 1; j <= n; j++) { + if (visit[j] >= k) { + count++; + } + } + sb.append(count + "\n"); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + q = Integer.parseInt(st.nextToken()); + + adj = new ArrayList[n+1]; + for (int i = 1; i <= n; i++) { + adj[i] = new ArrayList<>(); + } + + for (int i = 0; i < n-1; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + adj[a].add(new int[] {b, c}); + adj[b].add(new int[] {a, c}); + } + } + + public static int bfs(int s) { + Queue queue = new LinkedList<>(); + queue.add(new int[] {s, Integer.MAX_VALUE}); + visit = new int[n+1]; + visit[s] = -1; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + for (int[] next : adj[cur[0]]) { + if (visit[next[0]] == 0) { + visit[next[0]] = Math.min(cur[1], next[1]); + queue.add(new int[] {next[0], Math.min(cur[1], next[1])}); + } + } + } + + return 0; + } +} From f1ef45f8c71da4621653072ee994794371532c5b Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 21 Oct 2022 14:47:38 +0900 Subject: [PATCH 116/163] =?UTF-8?q?[BOJ-4811-JAVA]=20=EC=95=8C=EC=95=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_4811.java | 78 +++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_4811.java diff --git a/java/BOJ/Gold/IV/G4_4811.java b/java/BOJ/Gold/IV/G4_4811.java new file mode 100644 index 0000000..72587f5 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_4811.java @@ -0,0 +1,78 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/4811 + * + * ? 제목: 알약 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 70세 박종수 할아버지는 매일 매일 약 반알을 먹는다. 손녀 선영이는 종수 할아버지에게 약이 N개 담긴 병을 선물로 주었다. + * 첫째 날에 종수는 병에서 약 하나를 꺼낸다. 그 다음, 그 약을 반으로 쪼개서 한 조각은 먹고, 다른 조각은 다시 병에 넣는다. + * 다음 날부터 종수는 병에서 약을 하나 꺼낸다. (약은 한 조각 전체 일 수도 있고, 쪼갠 반 조각 일 수도 있다) 반 조각이라면 그 약을 먹고, 아니라면 반을 쪼개서 한 조각을 먹고, 다른 조각은 다시 병에 넣는다. + * 종수는 손녀에게 한 조각을 꺼낸 날에는 W를, 반 조각을 꺼낸 날에는 H 보낸다. 손녀는 할아버지에게 받은 문자를 종이에 기록해 놓는다. 총 2N일이 지나면 길이가 2N인 문자열이 만들어지게 된다. 이때, 가능한 서로 다른 문자열의 개수는 총 몇 개일까? + * + * ? 입력 & 파싱 + * 입력은 최대 1000개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄이며, 병에 들어있는 약의 개수 N ≤ 30 가 주어진다. + * 입력의 마지막 줄에는 0이 하나 주어진다. + * + * 6 -> n + * 1 -> n + * 4 -> n + * 2 -> n + * 3 -> n + * 30 -> n + * 0 -> end + * + * ? 출력 + * 각 테스트 케이스에 대해서 가능한 문자열의 개수를 출력한다. + * + * 132 + * 1 + * 14 + * 2 + * 5 + * 3814986502092304 + * + * ? 채점 결과 + * * 시간: 0.08초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.IV; + +import java.io.*; + +public class G4_4811 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + public static void main(String[] args) throws IOException { + int n = -1; + + StringBuffer sb = new StringBuffer(); + long[] dp = new long[31]; + dp[0] = 1; + dp[1] = 1; + dp[2] = 2; + + for (int i = 3; i <= 30; i++) { + long total = 0; + for (int j = 0; j < i; j++) { + total += (dp[j] * dp[i - j - 1]); + } + dp[i] = total; + } + + while ((n = Integer.parseInt(br.readLine())) != 0) { + sb.append(dp[n] + "\n"); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } +} From b8018d7d568398163b955490f74dbc9ada4315cb Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 22 Oct 2022 14:14:42 +0900 Subject: [PATCH 117/163] =?UTF-8?q?[BOJ-1981-JAVA]=20=EB=B0=B0=EC=97=B4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_1981.java | 128 +++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 java/BOJ/Gold/I/G1_1981.java diff --git a/java/BOJ/Gold/I/G1_1981.java b/java/BOJ/Gold/I/G1_1981.java new file mode 100644 index 0000000..f09dc87 --- /dev/null +++ b/java/BOJ/Gold/I/G1_1981.java @@ -0,0 +1,128 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1981 + * + * ? 제목: 배열에서 이동 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * n×n짜리의 배열이 하나 있다. 이 배열의 (1, 1)에서 (n, n)까지 이동하려고 한다. 이동할 때는 상, 하, 좌, 우의 네 인접한 칸으로만 이동할 수 있다. + * 이와 같이 이동하다 보면, 배열에서 몇 개의 수를 거쳐서 이동하게 된다. 이동하기 위해 거쳐 간 수들 중 최댓값과 최솟값의 차이가 가장 작아지는 경우를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 n(2 ≤ n ≤ 100)이 주어진다. 다음 n개의 줄에는 배열이 주어진다. 배열의 각 수는 0보다 크거나 같고, 200보다 작거나 같은 정수이다. + * + * 5 -> n + * 1 1 3 6 8 -> arr[0][0] ~ arr[0][n-1] + * 1 2 2 5 5 + * 4 4 0 3 3 + * 8 0 2 3 4 + * 4 3 0 2 1 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 첫째 줄에 (최대 - 최소)가 가장 작아질 때의 그 값을 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 0.508초 + * * 메모리: 293MB + * * 언어: JAVA8 + * * 시도: 8 + */ +package Gold.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; + +public class G1_1981 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n; + static int[][] arr; + + static int MIN = 200; + static int MAX = 0; + static boolean[][] visit; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + + int left = 0; + int right = MAX - MIN; + while (left <= right) { + int gap = (left + right) / 2; + boolean canGo = bfs(gap); + + if (canGo) { + right = gap-1; + } else { + left = gap+1; + } + } + + System.out.println(left); + } + + public static boolean bfs(int gap) { + Queue queue; + for (int m = MIN; m + gap <= MAX; m++) { + if (arr[0][0] < m || m + gap < arr[0][0]) { + continue; + } + + queue = new LinkedList<>(); + visit = new boolean[n][n]; + visit[0][0] = true; + queue.add(new int[] {0, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == n-1 && cur[1] == n-1) { + return true; + } + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= n || visit[nx][ny]) { + continue; + } + + if (m <= arr[nx][ny] && arr[nx][ny] <= m + gap) { + visit[nx][ny] = true; + queue.add(new int[] {nx, ny}); + } + + } + } + } + + return false; + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + + arr = new int[n][n]; + visit = new boolean[n][n]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + MAX = Math.max(MAX, arr[i][j]); + MIN = Math.min(MIN, arr[i][j]); + } + } + } +} From 0be39dabf2bb12271b4f54ef0d89bb5eefea3de3 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 23 Oct 2022 13:54:25 +0900 Subject: [PATCH 118/163] =?UTF-8?q?[BOJ-2240-JAVA]=20=EC=9E=90=EB=91=90?= =?UTF-8?q?=EB=82=98=EB=AC=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_2240.java | 100 +++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_2240.java diff --git a/java/BOJ/Gold/V/G5_2240.java b/java/BOJ/Gold/V/G5_2240.java new file mode 100644 index 0000000..5763129 --- /dev/null +++ b/java/BOJ/Gold/V/G5_2240.java @@ -0,0 +1,100 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2240 + * + * ? 제목: 자두나무 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 자두는 자두를 좋아한다. 그래서 집에 자두나무를 심어두고, 여기서 열리는 자두를 먹고는 한다. 하지만 자두는 키가 작아서 자두를 따먹지는 못하고, 자두가 떨어질 때까지 기다린 다음에 떨어지는 자두를 받아서 먹고는 한다. 자두를 잡을 때에는 자두가 허공에 있을 때 잡아야 하는데, 이는 자두가 말랑말랑하여 바닥에 떨어지면 못 먹을 정도로 뭉개지기 때문이다. + * 매 초마다, 두 개의 나무 중 하나의 나무에서 열매가 떨어지게 된다. 만약 열매가 떨어지는 순간, 자두가 그 나무의 아래에 서 있으면 자두는 그 열매를 받아먹을 수 있다. 두 개의 나무는 그다지 멀리 떨어져 있지 않기 때문에, 자두는 하나의 나무 아래에 서 있다가 다른 나무 아래로 빠르게(1초보다 훨씬 짧은 시간에) 움직일 수 있다. 하지만 자두는 체력이 그다지 좋지 못해서 많이 움직일 수는 없다. + * 자두는 T(1≤T≤1,000)초 동안 떨어지게 된다. 자두는 최대 W(1≤W≤30)번만 움직이고 싶어 한다. 매 초마다 어느 나무에서 자두가 떨어질지에 대한 정보가 주어졌을 때, 자두가 받을 수 있는 자두의 개수를 구해내는 프로그램을 작성하시오. 자두는 1번 자두나무 아래에 위치해 있다고 한다. + * + * ? 입력 + * 첫째 줄에 두 정수 T, W가 주어진다. 다음 T개의 줄에는 각 순간에 자두가 떨어지는 나무의 번호가 1 또는 2로 주어진다. + * + * 7 2 -> t w + * 2 -> a + * 1 -> a + * 1 -> a + * 2 -> a + * 2 -> a + * 1 -> a + * 1 -> a + * + * ? 출력 + * 첫째 줄에 자두가 받을 수 있는 자두의 최대 개수를 출력한다. + * + * 6 + * + * ? 채점 결과 + * * 시간: 0.08초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G5_2240 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int t, w; + static int[] arr; + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); + for (int i = 1; i <= t; i++) { + dp[0][i] = dp[0][i - 1]; + + if (arr[i] == 1) { + dp[0][i]++; + } + } + + for (int i = 1; i <= w; i++) { + for (int j = 1; j <= t; j++) { + if (i % 2 == 0) { // 1번 나무 + dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j - 1]); + + if (arr[j] == 1) { + dp[i][j]++; + } + } else { // 2번 나무 + dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j - 1]); + if (arr[j] == 2) { + dp[i][j]++; + } + } + } + } + + int max = 0; + for (int i = 0; i <= w; i++) { + max = Math.max(max, dp[i][t]); + } + + System.out.println(max); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + t = Integer.parseInt(st.nextToken()); + w = Integer.parseInt(st.nextToken()); + + arr = new int[t + 1]; + dp = new int[w + 1][t + 1]; + + for (int i = 1; i <= t; i++) { + int a = Integer.parseInt(br.readLine()); + arr[i] = a; + } + } +} From 8e24424def3175cdf0a687862906ec0dc4ff48b7 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 24 Oct 2022 10:46:51 +0900 Subject: [PATCH 119/163] =?UTF-8?q?[BOJ-17352-JAVA]=20=EC=97=AC=EB=9F=AC?= =?UTF-8?q?=EB=B6=84=EC=9D=98=20=EB=8B=A4=EB=A6=AC=EA=B0=80=20=EB=90=98?= =?UTF-8?q?=EC=96=B4=EB=93=9C=EB=A6=AC=EA=B2=A0=EC=8A=B5=EB=8B=88=EB=8B=A4?= =?UTF-8?q?!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_17352.java | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_17352.java diff --git a/java/BOJ/Gold/V/G5_17352.java b/java/BOJ/Gold/V/G5_17352.java new file mode 100644 index 0000000..7bf04fb --- /dev/null +++ b/java/BOJ/Gold/V/G5_17352.java @@ -0,0 +1,93 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17352 + * + * ? 제목: 여러분의 다리가 되어 드리겠습니다! + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 선린월드에는 N개의 섬이 있다. 섬에는 1, 2, ..., N의 번호가 하나씩 붙어 있다. 그 섬들을 N - 1개의 다리가 잇고 있으며, 어떤 두 섬 사이든 다리로 왕복할 수 있다. + * 어제까지는 그랬다. + * "왜 다리가 N - 1개밖에 없냐, 통행하기 불편하다"며 선린월드에 불만을 갖던 욱제가 다리 하나를 무너뜨렸다! 안 그래도 불편한 통행이 더 불편해졌다. 서로 왕복할 수 없는 섬들이 생겼기 때문이다. 일단 급한 대로 정부는 선린월드의 건축가를 고용해, 서로 다른 두 섬을 다리로 이어서 다시 어떤 두 섬 사이든 왕복할 수 있게 하라는 지시를 내렸다. + * 그런데 그 건축가가 당신이다! 안 그래도 천하제일 코딩대회에 참가하느라 바쁜데... + * + * ? 입력 & 파싱 + * 첫 줄에 정수 N이 주어진다. (2 ≤ N ≤ 300,000) + * 그 다음 N - 2개의 줄에는 욱제가 무너뜨리지 않은 다리들이 잇는 두 섬의 번호가 주어진다. + * + * 4 -> n + * 1 2 -> a b + * 1 3 -> a b + * + * ? 출력 + * 다리로 이을 두 섬의 번호를 출력한다. 여러 가지 방법이 있을 경우 그 중 아무거나 한 방법만 출력한다. + * + * 1 4 + * + * ? 채점 결과 + * *시간 0.596초 + * * 메모리: 90MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.V; + +import java.io.*; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G5_17352 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n; + static int[] parent; + + public static void main(String[] args) throws IOException { + n = Integer.parseInt(br.readLine()); + parent = IntStream.range(0, n+1).toArray(); + StringBuffer sb = new StringBuffer(); + + + for (int i = 0; i < n-2; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + union(a, b); + } + + for (int i = 2; i <= n; i++) { + if (findParent(i) != 1) { + sb.append(1 + " " + i); + break; + } + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + public static void union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + } +} From 72c44e3ac17de5b1db605bdc08ce953d89e6b105 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 25 Oct 2022 12:02:14 +0900 Subject: [PATCH 120/163] =?UTF-8?q?[BOJ-1562-JAVA]=20=EA=B3=84=EB=8B=A8=20?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/I/G1_1562.java | 72 ++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 java/BOJ/Gold/I/G1_1562.java diff --git a/java/BOJ/Gold/I/G1_1562.java b/java/BOJ/Gold/I/G1_1562.java new file mode 100644 index 0000000..b58b408 --- /dev/null +++ b/java/BOJ/Gold/I/G1_1562.java @@ -0,0 +1,72 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1562 + *

+ * ? 제목: 계단 수 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + *

+ * ? 문제 + * 45656이란 수를 보자. + * 이 수는 인접한 모든 자리의 차이가 1이다. 이런 수를 계단 수라고 한다. + * N이 주어질 때, 길이가 N이면서 0부터 9까지 숫자가 모두 등장하는 계단 수가 총 몇 개 있는지 구하는 프로그램을 작성하시오. 0으로 시작하는 수는 계단수가 아니다. + *

+ * ? 입력 & 파싱 + * 첫째 줄에 N이 주어진다. N은 1보다 크거나 같고, 100보다 작거나 같은 자연수이다. + *

+ * 10 -> n + *

+ * ? 출력 + * 첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다. + *

+ * 1 + *

+ * ? 채점 결과 + * * 시간: 0.124초 + * * 메모리: 16MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class G1_1562 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static void main(String[] args) throws IOException { + int n = Integer.parseInt(br.readLine()); + int div = 1_000_000_000; + + int[][][] dp = new int[n + 1][10][1 << 10]; + + for (int i = 1; i <= 9; i++) { + dp[1][i][1 << i] = 1; + } + + for (int i = 1; i < n; i++) { + for (int j = 0; j <= 9; j++) { + for (int k = 0; k < (1 << 10); k++) { + if (j > 0) { + int bit = k | (1 << (j - 1)); + dp[i + 1][j - 1][bit] = (dp[i + 1][j - 1][bit] + dp[i][j][k]) % div; + } + + if (j < 9) { + int bit = k | (1 << (j + 1)); + dp[i + 1][j + 1][bit] = (dp[i + 1][j + 1][bit] + dp[i][j][k]) % div; + } + } + } + } + + int answer = 0; + for (int i = 0; i <= 9; i++) { + answer = (answer + dp[n][i][(1 << 10) - 1]) % div; + } + + System.out.println(answer); + } +} \ No newline at end of file From 6d2d5fdf3cbcadf06e352880c17dcd886afa4e12 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 26 Oct 2022 18:57:48 +0900 Subject: [PATCH 121/163] =?UTF-8?q?[BOJ-11058-JAVA]=20=ED=81=AC=EB=A6=AC?= =?UTF-8?q?=EB=B3=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_11058.java | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_11058.java diff --git a/java/BOJ/Gold/V/G5_11058.java b/java/BOJ/Gold/V/G5_11058.java new file mode 100644 index 0000000..42c01a0 --- /dev/null +++ b/java/BOJ/Gold/V/G5_11058.java @@ -0,0 +1,58 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11058 + * + * ? 문제: 크리보드 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 크리보드는 kriii가 만든 신기한 키보드이다. 크리보드에는 버튼이 4개만 있으며, 하는 역할은 다음과 같다. + * 화면에 A를 출력한다. + * Ctrl-A: 화면을 전체 선택한다 + * Ctrl-C: 전체 선택한 내용을 버퍼에 복사한다 + * Ctrl-V: 버퍼가 비어있지 않은 경우에는 화면에 출력된 문자열의 바로 뒤에 버퍼의 내용을 붙여넣는다. + * 크리보드의 버튼을 총 N번 눌러서 화면에 출력된 A개수를 최대로하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 N(1 ≤ N ≤ 100)이 주어진다. + * + * 3 -> n + * + * ? 출력 + * 크리보드의 버튼을 총 N번 눌러서 화면에 출력할 수 있는 A 개수의 최댓값을 출력한다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 0.076초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class G5_11058 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static void main(String[] args) throws IOException { + int n = Integer.parseInt(br.readLine()); + long[] dp = new long[n+1]; + + dp[1] = 1; + for (int i = 1; i <= n; i++) { + dp[i] = i; + for (int j = 2; j <= 5; j++) { + if (i - j - 1 > 0) { + dp[i] = Math.max(dp[i-(j+1)] * j, dp[i]); + } + } + } + + System.out.println(dp[n]); + } +} From 39ce7d9dcdda312875477140722f240de2842510 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 27 Oct 2022 15:29:35 +0900 Subject: [PATCH 122/163] =?UTF-8?q?[BOJ-14395-JAVA]=204=EC=97=B0=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_14395.java | 117 ++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_14395.java diff --git a/java/BOJ/Gold/V/G5_14395.java b/java/BOJ/Gold/V/G5_14395.java new file mode 100644 index 0000000..10f885b --- /dev/null +++ b/java/BOJ/Gold/V/G5_14395.java @@ -0,0 +1,117 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14395 + * + * ? 제목: 4연산 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 정수 s가 주어진다. 정수 s의 값을 t로 바꾸는 최소 연산 횟수를 구하는 프로그램을 작성하시오. + * 사용할 수 있는 연산은 아래와 같다. + * + * s = s + s; (출력: +) + * s = s - s; (출력: -) + * s = s * s; (출력: *) + * s = s / s; (출력: /) (s가 0이 아닐때만 사용 가능) + * + * ? 입력 & 파싱 + * 첫째 줄에 s와 t가 주어진다. (1 ≤ s, t ≤ 109) + * + * 7 392 -> s t + * + * ? 출력 + * 첫째 줄에 정수 s를 t로 바꾸는 방법을 출력한다. s와 t가 같은 경우에는 0을, 바꿀 수 없는 경우에는 -1을 출력한다. 가능한 방법이 여러 가지라면, 사전 순으로 앞서는 것을 출력한다. + * 연산의 아스키 코드 순서는 '*', '+', '-', '/' 이다. + * + * +*+ + * + * ? 채점 결과 + * * 시간: 0.124초 + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 9 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +class NumberFour { + long num; + String op; + + public NumberFour(long num, String op) { + this.num = num; + this.op = op; + } +} + +public class G5_14395 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + public static void main(String[] args) throws IOException { + st = new StringTokenizer(br.readLine()); + long s = Long.parseLong(st.nextToken()); + long t = Long.parseLong(st.nextToken()); + + HashSet set = new HashSet<>(); + + if (s == t) { + System.out.println(0); + } else if (t == 1) { + System.out.println("/"); + } else { + Queue queue = new LinkedList<>(); + queue.add(new NumberFour(s, "")); + boolean find = false; + + while (!queue.isEmpty()) { + NumberFour nf = queue.poll(); + + if (nf.num == t) { + System.out.println(nf.op); + find = true; + break; + } + + long prod = nf.num * nf.num; + String prodOp = nf.op + "*"; + + long sum = 2 * nf.num; + String sumOp = nf.op + "+"; + + long div = 1; + String divOp = nf.op + "/"; + + + if (!set.contains(prod)) { + set.add(prod); + queue.add(new NumberFour(prod, prodOp)); + } + + + if (!set.contains(sum)) { + set.add(sum); + queue.add(new NumberFour(sum, sumOp)); + } + + + if (!set.contains(div)) { + set.add(div); + queue.add(new NumberFour(div, divOp)); + } + } + + if (!find) { + System.out.println(-1); + } + } + } +} From 643d85c4e16e9a346111f784a8533c94ef3e8c98 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 28 Oct 2022 11:19:27 +0900 Subject: [PATCH 123/163] =?UTF-8?q?[BOJ-17836-JAVA]=20=EA=B3=B5=EC=A3=BC?= =?UTF-8?q?=EB=8B=98=EC=9D=84=20=EA=B5=AC=ED=95=B4=EB=9D=BC!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_17836.java | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_17836.java diff --git a/java/BOJ/Gold/V/G5_17836.java b/java/BOJ/Gold/V/G5_17836.java new file mode 100644 index 0000000..c32dcb9 --- /dev/null +++ b/java/BOJ/Gold/V/G5_17836.java @@ -0,0 +1,121 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17836 + * + * ? 제목: 공주님을 구해라! + * ? 시간 제한: 1초 + * ? 메모리 제한; 256MB + * + * ? 문제 + * 용사는 마왕이 숨겨놓은 공주님을 구하기 위해 (N, M) 크기의 성 입구 (1,1)으로 들어왔다. 마왕은 용사가 공주를 찾지 못하도록 성의 여러 군데 마법 벽을 세워놓았다. 용사는 현재의 가지고 있는 무기로는 마법 벽을 통과할 수 없으며, 마법 벽을 피해 (N, M) 위치에 있는 공주님을 구출해야만 한다. + * 마왕은 용사를 괴롭히기 위해 공주에게 저주를 걸었다. 저주에 걸린 공주는 T시간 이내로 용사를 만나지 못한다면 영원히 돌로 변하게 된다. 공주님을 구출하고 프러포즈 하고 싶은 용사는 반드시 T시간 내에 공주님이 있는 곳에 도달해야 한다. 용사는 한 칸을 이동하는 데 한 시간이 걸린다. 공주님이 있는 곳에 정확히 T시간만에 도달한 경우에도 구출할 수 있다. 용사는 상하좌우로 이동할 수 있다. + * 성에는 이전 용사가 사용하던 전설의 명검 "그람"이 숨겨져 있다. 용사가 그람을 구하면 마법의 벽이 있는 칸일지라도, 단숨에 벽을 부수고 그 공간으로 갈 수 있다. "그람"은 성의 어딘가에 반드시 한 개 존재하고, 용사는 그람이 있는 곳에 도착하면 바로 사용할 수 있다. 그람이 부술 수 있는 벽의 개수는 제한이 없다. + * 우리 모두 용사가 공주님을 안전하게 구출 할 수 있는지, 있다면 얼마나 빨리 구할 수 있는지 알아보자. + * + * ? 입력 & 파싱 + * 첫 번째 줄에는 성의 크기인 N, M 그리고 공주에게 걸린 저주의 제한 시간인 정수 T가 주어진다. 첫 줄의 세 개의 수는 띄어쓰기로 구분된다. (3 ≤ N, M ≤ 100, 1 ≤ T ≤ 10000) + * 두 번째 줄부터 N+1번째 줄까지 성의 구조를 나타내는 M개의 수가 띄어쓰기로 구분되어 주어진다. 0은 빈 공간, 1은 마법의 벽, 2는 그람이 놓여있는 공간을 의미한다. (1,1)과 (N,M)은 0이다. + * + * 6 6 16 -> n m t + * 0 0 0 0 1 1 -> arr[0][0] ~ arr[0][m-1] + * 0 0 0 0 0 2 + * 1 1 1 0 1 0 + * 0 0 0 0 0 0 + * 0 1 1 1 1 1 + * 0 0 0 0 0 0 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 용사가 제한 시간 T시간 이내에 공주에게 도달할 수 있다면, 공주에게 도달할 수 있는 최단 시간을 출력한다. + * 만약 용사가 공주를 T시간 이내에 구출할 수 없다면, "Fail"을 출력한다. + * + * 10 + * + * ? 채점 결과 + * * 시간: 0.144초 + * * 메모리: 15MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.V; + +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 G5_17836 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m, t; + static int[][] arr; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + int answer = bfs(); + + if (answer <= t && answer != -1) { + System.out.println(answer); + } else { + System.out.println("Fail"); + } + } + + private static int bfs() { + Queue queue = new LinkedList<>(); + boolean[][][] visit = new boolean[n][m][2]; + queue.add(new int[] {0, 0, 0, 0}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == n-1 && cur[1] == m-1) { + return cur[2]; + } + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + continue; + } + + if (arr[nx][ny] == 2) { + arr[nx][ny] = 0; + visit[nx][ny][0] = true; + queue.add(new int[] {nx, ny, cur[2]+1, 1}); + } else if (arr[nx][ny] == 0 && !visit[nx][ny][cur[3]]) { + visit[nx][ny][cur[3]] = true; + queue.add(new int[] {nx, ny, cur[2]+1, cur[3]}); + } else if (arr[nx][ny] == 1 && cur[3] == 1 && !visit[nx][ny][0]) { + visit[nx][ny][0] = true; + queue.add(new int[] {nx, ny, cur[2]+1, 1}); + } + } + } + + return -1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + t = Integer.parseInt(st.nextToken()); + + arr = new int[n][m]; + + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 3b02a2dc16bd97795903eb3a9cc0a011baa252ab Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 29 Oct 2022 14:53:53 +0900 Subject: [PATCH 124/163] =?UTF-8?q?[BOJ-2169-JAVA]=20=EB=A1=9C=EB=B4=87=20?= =?UTF-8?q?=EC=A1=B0=EC=A2=85=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_2169.java | 109 ++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_2169.java diff --git a/java/BOJ/Gold/II/G2_2169.java b/java/BOJ/Gold/II/G2_2169.java new file mode 100644 index 0000000..ccb0e15 --- /dev/null +++ b/java/BOJ/Gold/II/G2_2169.java @@ -0,0 +1,109 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/2169 + *

+ * ? 제목: 로봇 조종하기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + *

+ * ? 문제 + * NASA에서는 화성 탐사를 위해 화성에 무선 조종 로봇을 보냈다. 실제 화성의 모습은 굉장히 복잡하지만, 로봇의 메모리가 얼마 안 되기 때문에 지형을 N×M 배열로 단순화 하여 생각하기로 한다. + * 지형의 고저차의 특성상, 로봇은 움직일 때 배열에서 왼쪽, 오른쪽, 아래쪽으로 이동할 수 있지만, 위쪽으로는 이동할 수 없다. 또한 한 번 탐사한 지역(배열에서 하나의 칸)은 탐사하지 않기로 한다. + * 각각의 지역은 탐사 가치가 있는데, 로봇을 배열의 왼쪽 위 (1, 1)에서 출발시켜 오른쪽 아래 (N, M)으로 보내려고 한다. 이때, 위의 조건을 만족하면서, 탐사한 지역들의 가치의 합이 최대가 되도록 하는 프로그램을 작성하시오. + *

+ * ? 입력 & 파싱 + * 첫째 줄에 N, M(1≤N, M≤1,000)이 주어진다. 다음 N개의 줄에는 M개의 수로 배열이 주어진다. 배열의 각 수는 절댓값이 100을 넘지 않는 정수이다. 이 값은 그 지역의 가치를 나타낸다. + *

+ * 5 5 -> n m + * 10 25 7 8 13 -> arr[1][1] ~ arr[1][m] + * 68 24 -78 63 32 + * 12 -69 100 -29 -25 + * -16 -22 -57 -33 99 + * 7 -76 -11 77 15 -> arr[n][1] ~ arr[n][m] + *

+ * ? 출력 + * 첫째 줄에 최대 가치의 합을 출력한다. + *

+ * 319 + *

+ * ? 채점 결과 + * * 시간: 0.628초 + * * 메모리: 116MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.II; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G2_2169 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m; + static int[][] arr; + + static int MIN = -100_000_000; + static boolean[][] visit; + static int[][][] dp; + + // 0 : 아래, 1: 오른쪽, 2: 왼쪽 + static int[] dx = {1, 0, 0}; + static int[] dy = {0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + + System.out.println( + Math.max( + findMax(1, 1, 0), + findMax(1, 1, 1)) + ); + } + + public static int findMax(int x, int y, int dir) { + if (x == n && y == m) { + return arr[n][m]; + } + + if (dp[x][y][dir] != 0) { + return dp[x][y][dir]; + } + + visit[x][y] = true; + int max = MIN; + + // 0 : 아래, 1: 오른쪽, 2: 왼쪽 + for (int i = 0; i < 3; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (1 <= nx && 1 <= ny && nx <= n && ny <= m && !visit[nx][ny]) { + max = Math.max(max, findMax(nx, ny, i) + arr[x][y]); + } + } + + visit[x][y] = false; + return dp[x][y][dir] = max; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n + 1][m + 1]; + visit = new boolean[n + 1][m + 1]; + dp = new int[n + 1][m + 1][3]; + + for (int i = 1; i <= n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 1; j <= m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From feffa7c91b592060fccbd70d916a45a0072c9d5a Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 30 Oct 2022 13:52:20 +0900 Subject: [PATCH 125/163] =?UTF-8?q?[BOJ-12886-JAVA]=20=EB=8F=8C=20?= =?UTF-8?q?=EA=B7=B8=EB=A3=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_12886.java | 89 ++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_12886.java diff --git a/java/BOJ/Gold/IV/G4_12886.java b/java/BOJ/Gold/IV/G4_12886.java new file mode 100644 index 0000000..2a68852 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_12886.java @@ -0,0 +1,89 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/12886 + * + * ? 제목: 돌 그룹 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 오늘 강호는 돌을 이용해 재미있는 게임을 하려고 한다. 먼저, 돌은 세 개의 그룹으로 나누어져 있으며 각각의 그룹에는 돌이 A, B, C개가 있다. 강호는 모든 그룹에 있는 돌의 개수를 같게 만들려고 한다. + * 강호는 돌을 단계별로 움직이며, 각 단계는 다음과 같이 이루어져 있다. + * 크기가 같지 않은 두 그룹을 고른다. 그 다음, 돌의 개수가 작은 쪽을 X, 큰 쪽을 Y라고 정한다. 그 다음, X에 있는 돌의 개수를 X+X개로, Y에 있는 돌의 개수를 Y-X개로 만든다. + * A, B, C가 주어졌을 때, 강호가 돌을 같은 개수로 만들 수 있으면 1을, 아니면 0을 출력하는 프로그램을 작성하시오. + * + * ? 입력 + * 첫째 줄에 A, B, C가 주어진다. (1 ≤ A, B, C ≤ 500) + * + * 10 15 36 -> A B C + * + * ? 출력 + * 돌을 같은 개수로 만들 수 있으면 1을, 아니면 0을 출력한다. + * + * 1 + * + * ? 채점 결과 + * * 시간: 0.288초 + * * 메모리: 94MB + * * 언어: JAVA8 + * * 시도: 4 + */ +package Gold.IV; + +import java.io.*; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G4_12886 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int A, B, C; + static int[][] dir = {{1, 2}, {0, 2}, {0, 1}}; + + public static void main(String[] args) throws IOException { + input(); + System.out.println(bfs()); + } + + public static int bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {A, B, C}); + boolean[][] visit = new boolean[1501][1501]; + visit[A][B] = true; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == cur[1] && cur[1] == cur[2]) { + return 1; + } + + for (int i = 0; i < 3; i++) { + if (cur[dir[i][0]] != cur[dir[i][1]]) { + int[] next = new int[3]; + next[i] = cur[i]; + + next[dir[i][0]] = cur[dir[i][0]] > cur[dir[i][1]] ? cur[dir[i][0]] - cur[dir[i][1]] : 2 * cur[dir[i][0]]; + next[dir[i][1]] = cur[dir[i][1]] > cur[dir[i][0]] ? cur[dir[i][1]] - cur[dir[i][0]] : 2 * cur[dir[i][1]]; + + if (!visit[next[dir[i][0]]][next[dir[i][1]]]) { + visit[next[dir[i][0]]][next[dir[i][1]]] = true; + queue.add(next); + } + } + } + } + + return 0; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + A = Integer.parseInt(st.nextToken()); + B = Integer.parseInt(st.nextToken()); + C = Integer.parseInt(st.nextToken()); + } +} From 864723881c1c149b0ef076721c03e1eae23dfef7 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Mon, 31 Oct 2022 20:22:39 +0900 Subject: [PATCH 126/163] =?UTF-8?q?[BOJ-1256-JAVA]=20=EC=82=AC=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_1256.java | 100 ++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_1256.java diff --git a/java/BOJ/Gold/II/G2_1256.java b/java/BOJ/Gold/II/G2_1256.java new file mode 100644 index 0000000..880759e --- /dev/null +++ b/java/BOJ/Gold/II/G2_1256.java @@ -0,0 +1,100 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1256 + * + * ? 제목: 사전 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 동호와 규완이는 212호에서 문자열에 대해 공부하고 있다. 김진영 조교는 동호와 규완이에게 특별 과제를 주었다. 특별 과제는 특별한 문자열로 이루어 진 사전을 만드는 것이다. 사전에 수록되어 있는 모든 문자열은 N개의 "a"와 M개의 "z"로 이루어져 있다. 그리고 다른 문자는 없다. 사전에는 알파벳 순서대로 수록되어 있다. + * 규완이는 사전을 완성했지만, 동호는 사전을 완성하지 못했다. 동호는 자신의 과제를 끝내기 위해서 규완이의 사전을 몰래 참조하기로 했다. 동호는 규완이가 자리를 비운 사이에 몰래 사전을 보려고 하기 때문에, 문자열 하나만 찾을 여유밖에 없다. + * N과 M이 주어졌을 때, 규완이의 사전에서 K번째 문자열이 무엇인지 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 세 정수 N, M, K가 순서대로 주어진다. + * + * 2 2 2 -> n m k + * + * ? 출력 + * 첫째 줄에 규완이의 사전에서 K번째 문자열을 출력한다. 만약 규완이의 사전에 수록되어 있는 문자열의 개수가 K보다 작으면 -1을 출력한다. + * + * azaz + * + * ? 제한 + * 1 ≤ N, M ≤ 100 + * 1 ≤ K ≤ 1,000,000,000 + * + * ? 채점 결과 + * * 시간: 0.124초 + * * 메모리: 14MB + * * 언어: JAVA11 + * * 시도: 4 + */ +package Gold.II; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class G2_1256 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m, k; + static int MAX = 1_000_000_000; + static int[][] dp; + + public static void main(String[] args) throws IOException { + input(); + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { + dp[i][j] = Math.min(dp[i - 1][j] + dp[i][j - 1], MAX); + } + } + + if (dp[n][m] < k) { + System.out.println(-1); + } else { + StringBuffer sb = new StringBuffer(); + + while (true) { + if (n == 0 || m == 0) { + sb.append("z".repeat(m)); + sb.append("a".repeat(n)); + break; + } + + if (dp[n - 1][m] >= k) { + sb.append("a"); + n--; + } else { + sb.append("z"); + k -= dp[n - 1][m]; + m--; + } + } + + System.out.println(sb); + } + + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + dp = new int[n + 1][m + 1]; + for (int i = 0; i <= n; i++) { + dp[i][0] = 1; + } + + for (int i = 0; i <= m; i++) { + dp[0][i] = 1; + } + } +} From 80d9a44c1b02821059cd6e372ebbb9d35d9cb020 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 1 Nov 2022 16:07:16 +0900 Subject: [PATCH 127/163] =?UTF-8?q?[BOJ-10423-JAVA]=20=EC=A0=84=EA=B8=B0?= =?UTF-8?q?=EA=B0=80=20=EB=B6=80=EC=A1=B1=ED=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_10423.java | 124 +++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_10423.java diff --git a/java/BOJ/Gold/II/G2_10423.java b/java/BOJ/Gold/II/G2_10423.java new file mode 100644 index 0000000..a89e1e5 --- /dev/null +++ b/java/BOJ/Gold/II/G2_10423.java @@ -0,0 +1,124 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/10423 + * + * ? 제목: 전기가 부족해 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 세계에서 GDP가 가장 높은 서강 나라는 소프트웨어와 하드웨어 기술이 모두 최고라서 IT강국이라 불리고, 2015년부터 세상에서 가장 살기 좋은 나라 1등으로 꼽히고 있다. + * 살기 좋은 나라 1등으로 꼽힌 이후 외국인 방문객들이 많아졌고, 그에 따라 전기 소비율이 증가하여 전기가 많이 부족한 상황이 되었다. 따라서 서강 나라의 대통령은 최근 개발이 완료된 YNY발전소 프로젝트를 진행 하기로 하였다. 발전소를 만들 때 중요한 것은 발전소 건물과 도시로 전기를 공급해 줄 케이블이다. 발전소는 이미 특정 도시에 건설되어 있고, 따라서 추가적으로 드는 비용은 케이블을 설치할 때 드는 비용이 전부이다. 이 프로젝트의 문제는 케이블을 설치할 때 드는 비용이 굉장히 크므로 이를 최소화해서 설치하여 모든 도시에 전기를 공급하는 것이다. 여러분은 N개의 도시가 있고 M개의 두 도시를 연결하는 케이블의 정보와 K개의 YNY발전소가 설치된 도시가 주어지면 케이블 설치 비용을 최소로 사용하여 모든 도시에 전기가 공급할 수 있도록 해결해야 한다. 중요한 점은 어느 한 도시가 두 개의 발전소에서 전기를 공급받으면 낭비가 되므로 케이블이 연결되어있는 도시에는 발전소가 반드시 하나만 존재해야 한다. 아래 Figure 1를 보자. 9개의 도시와 3 개의 YNY발전소(A,B,I)가 있고, 각각의 도시들을 연결할 때 드는 비용이 주어진다. + * 이 예제에서 모든 도시에 전기를 공급하기 위하여 설치할 케이블의 최소 비용은 22이고, Figure 2의 굵은 간선이 연결한 케이블이다. B 도시는 연결된 도시가 하나도 없지만, 발전소가 설치된 도시는 전기가 공급될 수 있기 때문에 상관없다. + * + * ? 입력 & 파싱 + * 첫째 줄에는 도시의 개수 N(1 ≤ N ≤ 1,000)과 설치 가능한 케이블의 수 M(1 ≤ M ≤ 100,000)개, 발전소의 개수 K(1 ≤ K ≤ N)개가 주어진다. 둘째 줄에는 발전소가 설치된 도시의 번호가 주어진다. 셋째 줄부터 M개의 두 도시를 연결하는 케이블의 정보가 u, v, w로 주어진다. 이는 u도시와 v도시를 연결하는 케이블을 설치할 때 w의 비용이 드는 것을 의미한다. w는 10,000보다 작거나 같은 양의 정수이다. + * + * 4 5 1 -> n m k + * 1 -> gen[0] ~ gen[k-1] + * 1 2 5 -> a b c + * 1 3 5 -> a b c + * 1 4 5 -> a b c + * 2 3 10 -> a b c + * 3 4 10 -> a b c + * + * ? 출력 + * 모든 도시에 전기를 공급할 수 있도록 케이블을 설치하는 데 드는 최소비용을 출력한다. + * + * 15 + * + * ? 채점 결과 + * * 시간: 0.568 + * * 메모리: 53MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.II; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +public class G2_10423 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m, k; + static int[] gen; + static boolean[] visit; + static ArrayList[] cable; + + public static void main(String[] args) throws IOException { + input(); + prim(); + } + + public static void prim() { + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[1] - b[1]); + for (int g : gen) { + visit[g] = true; + for (int[] c : cable[g]) { + if (!visit[c[0]]) { + pq.add(c); + } + } + } + + int cost = 0; + int count = k; + while (!pq.isEmpty()) { + if (count >= n) { + break; + } + + int[] cur = pq.poll(); + if (visit[cur[0]]) { + continue; + } + + cost += cur[1]; + count++; + visit[cur[0]] = true; + + for (int[] next : cable[cur[0]]) { + if (!visit[next[0]]) { + pq.add(next); + } + } + } + + System.out.println(cost); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + st = new StringTokenizer(br.readLine()); + gen = new int[k]; + for (int i = 0; i < k; i++) { + gen[i] = Integer.parseInt(st.nextToken()); + } + + visit = new boolean[n + 1]; + cable = new ArrayList[n + 1]; + for (int i = 1; i <= n; i++) { + cable[i] = new ArrayList<>(); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + cable[a].add(new int[]{b, c}); + cable[b].add(new int[]{a, c}); + } + } +} From a66e54788166d6ad689812f3ee0f843f3f5e4863 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 2 Nov 2022 10:45:40 +0900 Subject: [PATCH 128/163] =?UTF-8?q?[BOJ-11562-JAVA]=20=EB=B0=B1=EC=96=91?= =?UTF-8?q?=EB=A1=9C=20=EB=B8=8C=EB=A0=88=EC=9D=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_11562.java | 149 ++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_11562.java diff --git a/java/BOJ/Gold/III/G3_11562.java b/java/BOJ/Gold/III/G3_11562.java new file mode 100644 index 0000000..b49e09f --- /dev/null +++ b/java/BOJ/Gold/III/G3_11562.java @@ -0,0 +1,149 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11562 + * + * ? 제목: 백양로 브레이크 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 서울 소재 Y모 대학교에서 대규모 공사를 진행하면서, 학교가 마치 미로처럼 변해버리고 말았다. 공사 이전까지는 어떤 건물에서 출발하더라도 다른 모든 건물로 갈 수 있는 길이 있었으나, 공사가 진행되면서 어떻게 한 건진 알 수 없지만 일방통행만 가능한 길이 많이 늘고 말았다. + * 컴퓨터과학과 학생 남규는 전공 수업을 듣고 교양 수업을 들으러 가던 중 길을 잃어 3일 밤낮을 헤매다가 공학관에서 종합관으로 가는 길은 존재하지 않는다는 결론을 내렸다. + * 3일 사이에 과제도 내지 못하고 출석도 하지 못해 학사경고 위기에 처한 남규는 전공을 살려 현재 일방통행인 길들 중 반드시 양방향으로 바꿔야만 하는 길이 몇 개인지 조사해 학교에 건의하기로 마음을 먹었다. + * 남규는 여러 건물들 사이를 직접 잇는 길들을 모두 조사했고, 그 중 어떤 길들이 일방통행인지, 또는 양방향 통행이 가능한지를 모두 체크했다. + * 남규의 프로그램은 간단하다. 출발지와 도착지를 입력하면 도착지까지 가기 위해 최소 몇 개의 길을 양방향으로 바꿔야만 하는지를 출력해준다. 프로그램이 완성되었다는 소문이 퍼지자, 남규처럼 길을 잃고 헤맨 경험이 있는 학생들은 남규에게 묻기 시작했다. + * "공학관에서 대강당 갈 수 있어?" + * "상경대 별관에서 학관으로는?" + * 남규는 매번 손으로 타이핑해 입력하고 결과를 보내주는 데에 지치고 말았다. + * 결국 앓아누운 남규를 위해 학생들의 질문을 해결할 새로운 프로그램을 만들어보자. + * + * ? 입력 + * 첫 줄에 Y대학교 건물의 수 n과 길의 수 m이 주어진다. (n ≤ 250, m ≤ n * (n - 1) / 2 ) + * 다음 m줄에 걸쳐, u v b (1 ≤ u ≤ n, 1 ≤ v ≤ n, u != v, b = 0 또는 1) 의 형태로 길에 대한 정보가 주어진다. + * b가 0일 경우 u에서 v로 가는 일방통행 길인 것이고, b가 1일 경우 u와 v를 잇는 양방향 길이다. + * 어떤 두 건물 사이를 잇는 길은 최대 한 개이다. + * 다음 줄에 학생들의 질문의 수 k가 주어진다. (1 ≤ k ≤ 30,000) + * 다음 k줄에 걸쳐 s e (1 ≤ s ≤ n, 1 ≤ e ≤ n)의 형태로 학생들의 질문들이 주어진다. + * 이는 질문한 학생이 건물 s에서 건물 e로 가고 싶다는 의미이다. + * + * 4 3 -> n m + * 1 2 0 -> u v b + * 2 3 1 -> u v b + * 3 4 0 -> u v b + * 7 -> k + * 1 1 -> s e + * 1 2 -> s e + * 2 1 -> s e + * 1 4 -> s e + * 4 1 -> s e + * 2 3 -> s e + * 4 3 -> s e + * + * ? 출력 + * 출력은 k줄에 걸쳐 이루어진다. + * 각 질문에 대해, 최소 몇 개의 일방통행인 길을 양방향 통행으로 바꿔야 출발지에서 도착지로 갈 수 있는지를 출력한다. + * 모든 길을 양방향으로 바꾸더라도 서로 도달 불가능한 건물은 없다. + * + * 0 + * 0 + * 1 + * 0 + * 2 + * 0 + * 1 + * + * ? 채점 결과 + * * 시간: 0.392초 + * * 메모리: 34MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +public class G3_11562 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int MAX = 100_000; + + static int n, m, k; + static int[][] floyd; + static ArrayList questions; + + public static void main(String[] args) throws IOException { + input(); + floydWarshall(); + + StringBuffer sb = new StringBuffer(); + for (int[] question : questions) { + sb.append(floyd[question[0]][question[1]] + "\n"); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void floydWarshall() { + for (int t = 1; t <= n; t++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (t == i || i == j) { + continue; + } + + if (floyd[i][j] > floyd[i][t] + floyd[t][j]) { + floyd[i][j] = floyd[i][t] + floyd[t][j]; + } + } + } + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + floyd = new int[n+1][n+1]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (i == j) { + continue; + } + + floyd[i][j] = MAX; + } + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int u = Integer.parseInt(st.nextToken()); + int v = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + floyd[u][v] = 0; + if (b == 0) { + floyd[v][u] = 1; + } else { + floyd[v][u] = 0; + } + } + + questions = new ArrayList<>(); + k = Integer.parseInt(br.readLine()); + for (int i = 0; i < k; i++) { + st = new StringTokenizer(br.readLine()); + int s = Integer.parseInt(st.nextToken()); + int e = Integer.parseInt(st.nextToken()); + questions.add(new int[] {s, e}); + } + } +} From b87074a45c83c24b9d896dce1b5deac0b1630f0e Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 3 Nov 2022 16:13:07 +0900 Subject: [PATCH 129/163] =?UTF-8?q?[BOJ-17182-JAVA]=20=EC=9A=B0=EC=A3=BC?= =?UTF-8?q?=20=ED=83=90=EC=82=AC=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_17182.java | 110 ++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_17182.java diff --git a/java/BOJ/Gold/III/G3_17182.java b/java/BOJ/Gold/III/G3_17182.java new file mode 100644 index 0000000..9f6495a --- /dev/null +++ b/java/BOJ/Gold/III/G3_17182.java @@ -0,0 +1,110 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17182 + * + * ? 제목: 우주 탐사선 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 우주 탐사선 ana호는 어떤 행성계를 탐사하기 위해 발사된다. 모든 행성을 탐사하는데 걸리는 최소 시간을 계산하려 한다. 입력으로는 ana호가 탐색할 행성의 개수와 ana호가 발사되는 행성의 위치와 ana호가 행성 간 이동을 하는데 걸리는 시간이 2차원 행렬로 주어진다. 행성의 위치는 0부터 시작하여 0은 행렬에서 0번째 인덱스에 해당하는 행성을 의미한다. 2차원 행렬에서 i, j 번 요소는 i 번째 행성에서 j 번째 행성에 도달하는데 걸리는 시간을 나타낸다. i와 j가 같을 때는 항상 0이 주어진다. 모든 행성을 탐사하는데 걸리는 최소 시간을 계산하여라. + * 탐사 후 다시 시작 행성으로 돌아올 필요는 없으며 이미 방문한 행성도 중복해서 갈 수 있다. + * + * ? 입력 + * 첫 번째 줄에는 행성의 개수 N과 ana호가 발사되는 행성의 위치 K가 주어진다. (2 ≤ N ≤ 10, 0 ≤ K < N) + * 다음 N 줄에 걸쳐 각 행성 간 이동 시간 Tij 가 N 개 씩 띄어쓰기로 구분되어 주어진다. (0 ≤ Tij ≤ 1000) + * + * 3 0 -> n start + * 0 30 1 -> arr[0][0] ~ arr[0][n-1] + * 1 0 29 + * 28 1 0 -> arr[n-1][0] ~ arr[n-1][n-1] + * + * ? 출력 + * 모든 행성을 탐사하기 위한 최소 시간을 출력한다. + * + * 2 + * + * ? 채점 결과 + * * 시간: 0.12초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 5 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; + +public class G3_17182 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, start; + static int[][] arr; + static ArrayList[] visit; + static int pass; + static int min = Integer.MAX_VALUE; + + public static void main(String[] args) throws IOException { + input(); + floydWarshall(); + backTracking(start, (1 << start), 0); + System.out.println(min); + } + + public static void backTracking(int cur, int visit, int time) { + if (visit == pass) { + min = Math.min(min, time); + return; + } + + for (int i = 0; i < n; i++) { + if (cur == i) { + continue; + } + + if ((visit & (1 << i)) == 0) { + backTracking(i, visit | (1 << i), time + arr[cur][i]); + } + } + } + + + public static void floydWarshall() { + for (int k = 0; k < n; k++) { + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (k == i || i == j) { + continue; + } + + if (arr[i][j] > arr[i][k] + arr[k][j]) { + arr[i][j] = arr[i][k] + arr[k][j]; + } + } + } + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + start = Integer.parseInt(st.nextToken()); + + pass = (1 << n) - 1; + + visit = new ArrayList[n]; + for (int i = 0; i < n; i++) { + visit[i] = new ArrayList<>(); + } + + arr = new int[n][n]; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < n; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 6b87c1c0845e7b778ff97f4320023f8e577e26e2 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 4 Nov 2022 17:58:29 +0900 Subject: [PATCH 130/163] =?UTF-8?q?[BOJ-14923-JAVA]=20=EB=AF=B8=EB=A1=9C?= =?UTF-8?q?=20=ED=83=88=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_14923.java | 133 +++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_14923.java diff --git a/java/BOJ/Gold/IV/G4_14923.java b/java/BOJ/Gold/IV/G4_14923.java new file mode 100644 index 0000000..099f718 --- /dev/null +++ b/java/BOJ/Gold/IV/G4_14923.java @@ -0,0 +1,133 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14923 + * + * ? 제목: 미로 탈출 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 홍익이는 사악한 마법사의 꾐에 속아 N x M 미로 (Hx, Hy) 위치에 떨어졌다. 다행히도 홍익이는 마법사가 만든 미로의 탈출 위치(Ex, Ey)를 알고 있다. 하지만 미로에는 곳곳에 마법사가 설치한 벽이 있어 홍익이가 탈출하기 어렵게 하고 있다. + * 홍익이는 마법사의 연구실에서 훔친 지팡이가 있어, 벽을 길로 만들 수 있다. 그렇지만, 안타깝게도 마법의 지팡이는 단 한 번만 사용할 수 있다. + * 이때, 홍익이를 도와 미로에서 탈출할 수 있는지 알아보고, 할 수 있다면 가장 빠른 경로의 거리 D는 얼마인지 알아보자. + * 인접한 칸으로 이동하는데 똑같은 시간이 들고, 벽을 부수는 데 시간이 걸리지 않는다. + * + * ? 입력 & 파싱 + * < 입력 설명 > + * N M + * Hx Hy + * Ex Ey + * N X M 행렬 + * + * 2 ≤ N ≤ 1000, 2 ≤ M ≤ 1000 + * 1 ≤ Hx, Hy, Ex, Ey ≤ 1000 + * (Hx, Hy)≠ (Ex, Ey) + * 행렬은 0과 1로만 이루어져 있고, 0이 빈 칸, 1이 벽이다. + * + * 5 6 -> n m + * 1 1 -> start[0], start[1] + * 5 6 -> end[0], end[1] + * 0 1 1 1 0 0 -> arr[0][0] ~ arr[0][m-1] + * 0 1 1 0 0 0 + * 0 1 0 0 1 0 + * 0 1 0 0 1 0 + * 0 0 0 1 1 0 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * D (탈출 할 수 없다면, -1을 출력한다.) + * + * 11 + * + * ? 채점 결과 + * * 시간: 0.696초 + * * 메모리: 118MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +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 G4_14923 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m; + static int[][] arr; + static int[] start; + static int[] end; + static int[][][] visit; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + int answer = bfs(); + System.out.println(answer); + } + + public static int bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[]{start[0], start[1], 1}); + visit[start[0]][start[1]][1] = 1; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == end[0] && cur[1] == end[1]) { + return visit[end[0]][end[1]][cur[2]] - 1; + } + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + continue; + } + + if (arr[nx][ny] == 1 && cur[2] == 1) { + if (visit[nx][ny][0] == 0) { + visit[nx][ny][0] = visit[cur[0]][cur[1]][cur[2]] + 1; + queue.add(new int[]{nx, ny, 0}); + } + + } else if (arr[nx][ny] == 0) { + if (visit[nx][ny][cur[2]] == 0) { + visit[nx][ny][cur[2]] = visit[cur[0]][cur[1]][cur[2]] + 1; + queue.add(new int[]{nx, ny, cur[2]}); + } + } + } + } + + return -1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + st = new StringTokenizer(br.readLine()); + start = new int[]{Integer.parseInt(st.nextToken()) - 1, Integer.parseInt(st.nextToken()) - 1}; + + st = new StringTokenizer(br.readLine()); + end = new int[]{Integer.parseInt(st.nextToken()) - 1, Integer.parseInt(st.nextToken()) - 1}; + + arr = new int[n][m]; + visit = new int[n][m][2]; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + } +} From 90e9c703f426a884026f4b76ee0cdb0dc10a49a5 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 5 Nov 2022 15:06:45 +0900 Subject: [PATCH 131/163] =?UTF-8?q?[BOJ-13418-JAVA]=20=ED=95=99=EA=B5=90?= =?UTF-8?q?=20=ED=83=90=EB=B0=A9=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_13418.java | 130 ++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_13418.java diff --git a/java/BOJ/Gold/III/G3_13418.java b/java/BOJ/Gold/III/G3_13418.java new file mode 100644 index 0000000..d2b7182 --- /dev/null +++ b/java/BOJ/Gold/III/G3_13418.java @@ -0,0 +1,130 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/13418 + * + * ? 제목: 학교 탐방하기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 국민대학교 홍보대사 국희는 여름방학을 맞아 고등학생들을 대상으로 학교 내부에 있는 건물을 소개해주는 일을 하게 되어 학교 건물을 차례로 소개할 수 있는 이동 경로를 짜보기로 하였다. 국민대학교는 북한산의 정기를 받는 위치에 있어 건물 간 연결된 길이 험난한 오르막길일 수도 있고, 내리막길일 수도 있다. 국희는 먼저 입구를 기준으로 건물 간 연결된 도로가 오르막길인지, 내리막길인지를 파악하여 오르막길인 경우 점선, 내리막길인 경우 실선으로 표시하였다. + * 건물을 구분하기 쉽도록 번호를 붙였고, 입구에는 숫자 0을 붙이기로 하였다. 그 다음 모든 건물을 방문하는 데 필요한 최소한의 길을 선택하여, 해당 길을 통해서만 건물들을 소개하기로 하였다. 이 과정은 굉장히 신중해야 하는데, 오르막길이 많이 포함되게 되면 굉장히 피곤해지기 때문이다. + * 얼마나 피곤해지는지 알아보기 위해 피로도를 계산하기로 하였다. 오르막길을 k번 오를 때, 피로도는 k2이 된다. 피로도의 계산은 최초 조사된 길을 기준으로만 한다. 즉, 내리막길로 내려갔다 다시 올라올 때 오르막길이 되는 경우는 고려하지 않는다. 입구는 항상 1번 건물과 연결된 도로를 가지며, 출발은 항상 입구에서 한다. + * 그림 1에서 모든 건물을 소개하기 위해 거쳐야 할 최소한의 도로는 4개임을 알 수 있다. 다음 2개의 그림은 그 4개의 도로를 뽑은 각각의 경우이다. 그림 2는 학교를 소개하는 데 총 3개의 오르막길을 오르게 되며 피로도가 9가 되는 최악의 코스가 된다. 그림 3은 오르막길을 1번만 오르게 되므로 학생들의 피로도는 1이 되는 최적의 코스가 된다. 이 경우 최악의 코스와 최적의 코스간 최종 피로도의 차이는 8이 된다. 국희는 최고의 프로그래머인 당신에게 위와 같은 방식으로 최악, 최선의 경로 간 피로도의 차이를 계산하는 프로그램의 제작을 부탁하였다. 프로그램을 작성하여 국희를 도와주자. + * + * ? 입력 & 파싱 + * 입력 데이터는 표준 입력을 사용한다. 입력은 1개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 건물의 개수 N(1 ≤ N ≤ 1,000)과 도로의 개수 M(1 ≤ M ≤ N(N-1)/2) 이 주어진다. 입력의 두 번째 줄부터 M+1개의 줄에는 A, B(1 ≤ A, B ≤ N), C 가 주어진다. 이는 A와 B 건물에 연결된 도로가 있다는 뜻이며, C는 0(오르막길) 또는 1(내리막길)의 값을 가진다. 같은 경로 상에 2개 이상의 도로가 주어지는 경우는 없으며, 입구는 항상 1번 건물과 연결되어 있다. 입구와 1번 도로 간의 연결 관계는 항상 2번째 줄에 주어진다. 입구에서 모든 건물로 갈 수 있음이 보장된다. + * + * 4 5 -> n m + * 0 1 1 -> a b c + * 1 2 0 -> a b c + * 1 4 0 -> a b c + * 4 2 1 -> a b c + * 3 4 1 -> a b c + * 2 3 0 -> a b c + * + * ? 출력 + * 출력은 표준 출력을 사용한다. 입력받은 데이터에 대해, 주어진 조건을 만족하는 최악의 경로에서의 피로도와 최적의 경로 간 피로도의 차이를 출력한다. + * + * 8 + * + * ? 채점 결과 + * * 시간: 0.864초 + * * 메모리: 170MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G3_13418 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m; + static boolean firstUp; + static int[] parent; + static ArrayList list; + + public static void main(String[] args) throws IOException { + input(); + + list.sort((a, b) -> b[2] - a[2]); + int k1 = kruskal(); + + list.sort((a, b) -> a[2] - b[2]); + int k2 = kruskal(); + + System.out.println(k2 - k1); + } + + public static int kruskal() { + int k = 0; + int count = 0; + parent = IntStream.range(0, n + 1).toArray(); + parent[1] = 0; + + for (int i = 0; i < m; i++) { + if (count == n - 1) { + break; + } + + int[] road = list.get(i); + if (findParent(road[0]) != findParent(road[1])) { + count++; + union(road[0], road[1]); + + if (road[2] == 0) { + k++; + } + } + } + + return firstUp ? (k + 1) * (k + 1) : k * k; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + list = new ArrayList<>(); + + for (int i = 0; i <= m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + if (a == 0 && b == 1 && c == 0) { + firstUp = true; + } + + list.add(new int[]{a, b, c}); + } + } + + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + public static void union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + } +} From dd7a028d2e9f0c2a5993d76af3a367389f75ee66 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 6 Nov 2022 14:01:43 +0900 Subject: [PATCH 132/163] =?UTF-8?q?[BOJ-11085-JAVA]=20=EA=B5=B0=EC=82=AC?= =?UTF-8?q?=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_11085.java | 116 ++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_11085.java diff --git a/java/BOJ/Gold/III/G3_11085.java b/java/BOJ/Gold/III/G3_11085.java new file mode 100644 index 0000000..fa6548a --- /dev/null +++ b/java/BOJ/Gold/III/G3_11085.java @@ -0,0 +1,116 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11085 + * + * ? 제목: 군사 이동 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 전쟁 당시 Baekjoon World의 국왕은 Cube World를 공격할 작전을 세운 적이 있습니다. Baekjoon World와 Cube World는 p개의 지점과 w개의 길로 표현됩니다. 모든 길은 양방향이며, 각 길마다 너비가 존재하여 이에 비례하는 수의 군사가 지나갈 수 있습니다. + * Baekjoon World의 국왕은 군사들이 뭉치는 것이 유리하다고 생각해서, 미리 Cube World로 가는 경로를 정해 두고 그 경로로만 모든 군사를 보냈습니다. Baekjoon World의 국왕은 총명해서, 경로 상에 있는 길 중 너비가 가장 좁은 길의 너비를 최대화하는 경로를 택했습니다. + * 그런데 전쟁 때문에 어느 길로 보냈는지에 대한 기록이 불타 없어져 버렸습니다. 전쟁사를 완성하려면 이 기록이 꼭 필요합니다. 위대한 과학자인 당신이 다시 복구해 주세요. + * + * ? 입력 & 파싱 + * 첫 줄에 p와 w가 공백을 사이에 두고 주어집니다. (2 ≤ p ≤ 1 000; 1 ≤ w ≤ 50 000) + * 다음 줄에 Baekjoon World의 수도 c와 Cube World의 수도 v가 공백을 사이에 두고 주어집니다. (0 ≤ c, v < p; c ≠ v) + * 다음 w줄에 길이 연결하는 두 지점 wstart, wend,와 길의 너비 wwidth가 공백을 사이에 두고 주어집니다. (0 ≤ wstart, wend < p; wstart ≠ wend; 1 ≤ wwidth ≤ 1 000) + * + * 7 11 -> n m + * 3 5 -> s e + * 0 1 15 -> a b c + * 0 2 23 -> a b c + * 1 2 16 -> a b c + * 1 3 27 -> a b c + * 2 4 3 -> a b c + * 2 6 21 -> a b c + * 3 4 14 -> a b c + * 3 5 10 -> a b c + * 4 5 50 -> a b c + * 4 6 9 -> a b c + * 5 6 42 -> a b c + * + * ? 출력 + * 첫 줄에 Baekjoon World의 국왕이 정한 경로 상에 있는 길 중 너비가 가장 좁은 길의 너비를 출력합니다. + * + * 16 + * + * ? 채점 결과 + * * 시간: 0.468초 + * * 메모리: 36MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.III; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +public class G3_11085 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int p, w, s, e; + static int[] visit; + static ArrayList[] list; + + public static void main(String[] args) throws IOException { + input(); + dijkstra(); + System.out.println(visit[e]); + } + + public static void dijkstra() { + PriorityQueue pq = new PriorityQueue<>((a, b) -> b[1] - a[1]); + pq.add(new int[]{s, 1000}); + visit[s] = 1000; + + while (!pq.isEmpty()) { + int[] cur = pq.poll(); + + if (visit[cur[0]] > cur[1]) { + continue; + } + + for (int[] next : list[cur[0]]) { + int minWidth = Math.min(cur[1], next[1]); + + if (visit[next[0]] < minWidth) { + visit[next[0]] = minWidth; + pq.add(new int[]{next[0], minWidth}); + } + } + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + p = Integer.parseInt(st.nextToken()); + w = Integer.parseInt(st.nextToken()); + + st = new StringTokenizer(br.readLine()); + s = Integer.parseInt(st.nextToken()); + e = Integer.parseInt(st.nextToken()); + + visit = new int[p]; + Arrays.fill(visit, -1); + list = new ArrayList[p]; + for (int i = 0; i < p; i++) { + list[i] = new ArrayList<>(); + } + + for (int i = 0; i < w; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + list[a].add(new int[]{b, c}); + list[b].add(new int[]{a, c}); + } + } +} From e8a5cd232d91562300deb34c8b1e27dc09ad309c Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 7 Nov 2022 16:11:23 +0900 Subject: [PATCH 133/163] =?UTF-8?q?[BOJ-21924-JAVA]=20=EB=8F=84=EC=8B=9C?= =?UTF-8?q?=20=EA=B1=B4=EC=84=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_21924.java | 137 +++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_21924.java diff --git a/java/BOJ/Gold/IV/G4_21924.java b/java/BOJ/Gold/IV/G4_21924.java new file mode 100644 index 0000000..186b13c --- /dev/null +++ b/java/BOJ/Gold/IV/G4_21924.java @@ -0,0 +1,137 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/21924 + * + * ? 제목: 도시 건설 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 채완이는 신도시에 건물 사이를 잇는 양방향 도로를 만들려는 공사 계획을 세웠다. + * 공사 계획을 검토하면서 비용이 생각보다 많이 드는 것을 확인했다. + * 채완이는 공사하는 데 드는 비용을 아끼려고 한다. + * 모든 건물이 도로를 통해 연결되도록 최소한의 도로를 만들려고 한다.* + * 위 그림에서 건물과 직선으로 표시된 도로, 해당 도로를 만들 때 드는 비용을 표시해놓은 지도이다.* + * 그림에 있는 도로를 다 설치할 때 드는 비용은 62이다. 모든 건물을 연결하는 도로만 만드는 비용은 27로 절약하는 비용은 35이다. + * 채완이는 도로가 너무 많아 절약되는 금액을 계산하는 데 어려움을 겪고 있다. + * 채완이를 대신해 얼마나 절약이 되는지 계산해주자. + * + * ? 입력 & 파싱 + * 첫 번째 줄에 건물의 개수 $N$ $(3 \le N \le 10^5 )$와 도로의 개수 $M$ + * $(2 \le M \le min( {N(N-1) \over 2}, 5×10^5)) $가 주어진다. + * 두 번째 줄 부터 $M + 1$줄까지 건물의 번호 $a$, $b$ $(1 \le a, b \le N, a ≠ b)$와 두 건물 사이 도로를 만들 때 드는 비용 $c (1 \le c \le 10^6)$가 주어진다. 같은 쌍의 건물을 연결하는 두 도로는 주어지지 않는다. + * + * 7 9 -> n m + * 1 2 15 -> a b c + * 2 3 7 -> a b c + * 1 3 3 -> a b c + * 1 4 8 -> a b c + * 3 5 6 -> a b c + * 4 5 4 -> a b c + * 4 6 12 -> a b c + * 5 7 1 -> a b c + * 6 7 6 -> a b c + * + * ? 출력 + * 예산을 얼마나 절약 할 수 있는지 출력한다. 만약 모든 건물이 연결되어 있지 않는다면 -1을 출력한다. + * + * 35 + * + * ? 채점 결과 + * * 시간: 1.240초 + * * 메모리: 190MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.IV; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G4_21924 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m; + static long totalCost; + static int[] parent; + static ArrayList list; + + public static void main(String[] args) throws IOException { + input(); + long cost = kruskal(); + if (cost == -1) { + System.out.println(-1); + } else { + System.out.println(totalCost - cost); + } + } + + public static long kruskal() { + int count = 0; + long cost = 0; + + for (int i = 0; i < m; i++) { + if (count == n-1) { + break; + } + + int[] road = list.get(i); + + if (union(road[0], road[1])) { + count++; + cost += road[2]; + } + } + + return count == n-1 ? cost : -1; + } + + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + public static boolean union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a == b) { + return false; + } + + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + return true; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + totalCost = 0; + + list = new ArrayList<>(); + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + list.add(new int[] {a, b, c}); + totalCost += c; + } + + list.sort((a, b) -> a[2] - b[2]); + parent = IntStream.range(0, n+1).toArray(); + } +} From 8c3ac2ad171ce9070c0d112378f6ef1c81ef53fa Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 8 Nov 2022 18:23:44 +0900 Subject: [PATCH 134/163] =?UTF-8?q?[BOJ-14284-JAVA]=20=EA=B0=84=EC=84=A0?= =?UTF-8?q?=20=EC=9D=B4=EC=96=B4=EA=B0=80=EA=B8=B0=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_14284.java | 116 ++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_14284.java diff --git a/java/BOJ/Gold/V/G5_14284.java b/java/BOJ/Gold/V/G5_14284.java new file mode 100644 index 0000000..6e80f1c --- /dev/null +++ b/java/BOJ/Gold/V/G5_14284.java @@ -0,0 +1,116 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14284 + * + * ? 제목: 간선 이어가기 2 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 정점 n개, 0개의 간선으로 이루어진 무방향 그래프가 주어진다. 그리고 m개의 가중치 간선의 정보가 있는 간선리스트가 주어진다. 간선리스트에 있는 간선 하나씩 그래프에 추가해 나갈 것이다. 이때, 특정 정점 s와 t가 연결이 되는 시점에서 간선 추가를 멈출 것이다. 연결이란 두 정점이 간선을 통해 방문 가능한 것을 말한다. + * s와 t가 연결이 되는 시점의 간선의 가중치의 합이 최소가 되게 추가하는 간선의 순서를 조정할 때, 그 최솟값을 구하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 정점의 개수 n, 간선리스트의 간선 수 m이 주어진다.(2≤n≤5000,1≤m≤100,000) + * 다음 m줄에는 a,b,c가 주어지는데, 이는 a와 b는 c의 가중치를 가짐을 말한다. (1≤a,b≤n,1≤c≤100,a≠b) + * 다음 줄에는 두 정점 s,t가 주어진다. (1≤s,t≤n,s≠t) + * 모든 간선을 연결하면 그래프는 연결 그래프가 됨이 보장된다. + * + * 8 9 -> n m + * 1 2 3 -> a b c + * 1 3 2 -> a b c + * 1 4 4 -> a b c + * 2 5 2 -> a b c + * 3 6 1 -> a b c + * 4 7 3 -> a b c + * 5 8 6 -> a b c + * 6 8 2 -> a b c + * 7 8 7 -> a b c + * 1 8 -> s e + * + * ? 출력 + * s와 t가 연결되는 시점의 간선의 가중치 합의 최솟값을 출력하시오, + * + * 5 + * + * ? 채점 결과 + * * 시간: 0.5초 + * * 메모리: 49MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.V; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +public class G5_14284 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m, s, e; + static ArrayList[] list; + static int[] visit; + + public static void main(String[] args) throws IOException { + input(); + int answer = bfs(); + System.out.println(answer - 1); + } + + public static int bfs() { + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[1] - b[1]); + pq.add(new int[]{s, 1}); + visit[s] = 1; + + while (!pq.isEmpty()) { + int[] cur = pq.poll(); + + if (visit[cur[0]] != 0 && visit[cur[0]] < cur[1]) { + continue; + } + + if (cur[0] == e) { + return cur[1]; + } + + for (int[] next : list[cur[0]]) { + if (visit[next[0]] == 0 || visit[next[0]] > cur[1] + next[1]) { + visit[next[0]] = cur[1] + next[1]; + pq.add(new int[]{next[0], visit[next[0]]}); + } + } + } + return -1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + visit = new int[n + 1]; + list = new ArrayList[n + 1]; + for (int i = 1; i <= n; i++) { + list[i] = new ArrayList<>(); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + list[a].add(new int[]{b, c}); + list[b].add(new int[]{a, c}); + } + + st = new StringTokenizer(br.readLine()); + s = Integer.parseInt(st.nextToken()); + e = Integer.parseInt(st.nextToken()); + } +} From d0f2f4e72acecc30109f34d8d35709a8f87c9031 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 9 Nov 2022 08:12:00 +0900 Subject: [PATCH 135/163] =?UTF-8?q?[BOJ-16397-JAVA]=20=ED=83=88=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_16397.java | 104 +++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_16397.java diff --git a/java/BOJ/Gold/IV/G4_16397.java b/java/BOJ/Gold/IV/G4_16397.java new file mode 100644 index 0000000..be05c6d --- /dev/null +++ b/java/BOJ/Gold/IV/G4_16397.java @@ -0,0 +1,104 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16397 + * + * ? 제목: 탈출 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 홍익이는 홍익대학교 프로그래밍 경진대회의 출제진이다. 홍익이는 새벽에 문제를 만들던 도중 뒤통수에 느껴지는 고통과 함께 정신을 잃었다. + * 홍익이는 좁은 방에서 눈을 떴다. 주변을 살펴보니 벽면에는 LED로 된 다섯 자리 십진수 N이, 그 옆에 T, G라는 알파벳과 함께 또 다른 정수 두 개가 쓰여 있었고, 벽 앞에는 버튼 A, B 두 개가 있었다. + * 버튼을 이리저리 눌러보던 똑똑한 홍익이는 어떻게 해야 방을 탈출할 수 있을지 금방 눈치챘다. + * 버튼과 수에 대해 홍익이가 알아낸 것은 다음과 같다. + * 버튼 A를 누르면 N이 1 증가한다. + * 버튼 B를 누르면 N에 2가 곱해진 뒤, 0이 아닌 가장 높은 자릿수의 숫자가 1 줄어든다. 예를 들어 123→146으로, 5→0으로, 3→5로 변한다. 단, N이 0이면 버튼 B를 눌러도 수가 변하지 않는다. + * LED가 다섯 자리까지밖에 없기 때문에 N이 99,999를 넘어가는 순간 탈출에 실패하게 된다. + * 버튼 B를 눌러 N에 2를 곱한 순간 수가 99,999를 넘어간다면, 높은 자릿수의 수를 1 낮췄을때 99,999를 넘지 않는다고 해도 탈출에 실패하게 된다. + * 또한 홍익이는 최대 T회 버튼을 누를 수 있고, 그 횟수 안에 LED로 표현된 N을 G와 같게 만들어야 탈출할 수 있다는 사실을 알아냈다. + * 똑똑한 홍익이는 이와중에 자존심이 발동해 버튼 누르는 횟수를 최소로 하여 방을 탈출하기로 했다. + * 홍익이의 방 탈출을 기원하며, 탈출에 필요한 최소의 버튼 횟수를 구하자. + * + * ? 입력 & 파싱 + * 첫 번째 줄에 N (0 ≤ N ≤ 99,999), T (1 ≤ T ≤ 99,999), G (0 ≤ G ≤ 99,999)가 공백 하나를 사이에 두고 주어진다. + * 각각 N은 LED로 표현된 수, T는 버튼을 누를 수 있는 최대 횟수, G는 탈출을 위해 똑같이 만들어야 하는 수를 뜻한다. + * + * 1 7 10 -> n t g + * + * ? 출력 + * 첫 번째 줄에 탈출에 필요한 최소의 버튼 횟수를 출력한다. + * 만약 탈출할 수 없다면 “ANG”을 따옴표 없이 출력한다. + * + * 7 + * + * ? 채점 결과 + * * 시간: 0.156초 + * * 메모리: 19MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.IV; + +import java.io.*; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G4_16397 { + static final int MAX = 100_000; + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + static int n, t, g; + static int[] visit; + + public static void main(String[] args) throws IOException { + input(); + int answer = bfs(); + System.out.println(answer == -1 ? "ANG" : answer); + } + + public static int bfs() { + Queue queue = new LinkedList<>(); + queue.add(n); + visit[n] = 1; + + while (!queue.isEmpty()) { + int cur = queue.poll(); + + if (visit[cur] > t+1) { + break; + } + + if (cur == g) { + return visit[cur]-1; + } + + // A + if (cur + 1 < MAX && visit[cur + 1] == 0) { + visit[cur + 1] = visit[cur] + 1; + queue.add(cur + 1); + } + + // B + int next = 2 * cur; + if (cur != 0 && next < MAX) { + next = next - (int) Math.pow(10, Integer.toString(next).length()-1); + if (visit[next] == 0) { + visit[next] = visit[cur] + 1; + queue.add(next); + } + } + } + return -1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + t = Integer.parseInt(st.nextToken()); + g = Integer.parseInt(st.nextToken()); + + visit = new int[MAX]; + } +} From f04e139c3fb9c63a2822dea5aff75275f016ba93 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 10 Nov 2022 13:19:20 +0900 Subject: [PATCH 136/163] =?UTF-8?q?[BOJ-14950-JAVA]=20=EC=A0=95=EB=B3=B5?= =?UTF-8?q?=EC=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_14950.java | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_14950.java diff --git a/java/BOJ/Gold/III/G3_14950.java b/java/BOJ/Gold/III/G3_14950.java new file mode 100644 index 0000000..a55e06c --- /dev/null +++ b/java/BOJ/Gold/III/G3_14950.java @@ -0,0 +1,122 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14950 + * + * ? 제목: 정복자 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 서강 나라는 N개의 도시와 M개의 도로로 이루어졌다. 모든 도시의 쌍에는 그 도시를 연결하는 도로로 구성된 경로가 있다. 각 도로는 양방향 도로이며, 각 도로는 사용하는데 필요한 비용이 존재한다. 각각 도시는 1번부터 N번까지 번호가 붙여져 있다. 그 중에서 1번 도시의 군주 박건은 모든 도시를 정복하고 싶어한다. + * 처음 점거하고 있는 도시는 1번 도시 뿐이다. 만약 특정 도시 B를 정복하고 싶다면, B와 도로로 연결된 도시들 중에서 적어도 하나를 정복하고 있어야 한다. 조건을 만족하는 도시 중에서 하나인 A를 선택하면, B를 정복하는 과정에서 A와 B를 연결하는 도로의 비용이 소모된다. 박건은 한번에 하나의 도시만 정복을 시도하고 언제나 성공한다. 한 번 도시가 정복되면, 모든 도시는 경계를 하게 되기 때문에 모든 도로의 비용이 t만큼 증가하게 된다. 한 번 정복한 도시는 다시 정복하지 않는다. + * 이때 박건이 모든 도시를 정복하는데 사용되는 최소 비용을 구하시오. + * + * ? 입력 + * 첫째 줄에 도시의 개수 N과 도로의 개수 M과 한번 정복할 때마다 증가하는 도로의 비용 t가 주어진다. N은 10000보다 작거나 같은 자연수이고, M은 30000보다 작거나 같은 자연수이다. t는 10이하의 자연수이다. + * M개의 줄에는 도로를 나타내는 세 자연수 A, B, C가 주어진다. A와 B사이에 비용이 C인 도로가 있다는 뜻이다. A와 B는 N이하의 서로 다른 자연수이다. C는 10000 이하의 자연수이다. + * + * 4 5 8 -> n m t + * 1 2 3 -> a b c + * 1 3 2 -> a b c + * 2 3 2 -> a b c + * 2 4 4 -> a b c + * 3 4 1 -> a b c + * + * ? 출력 + * 모든 도시를 정복하는데 사용되는 최소 비용을 출력하시오. + * + * 29 + * + * ? 채점 결과 + * * 시간: 0.468초 + * * 메모리: 31MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.StringTokenizer; +import java.util.stream.IntStream; + +public class G3_14950 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n, m, t; + static int[] parent; + static ArrayList list; + + public static void main(String[] args) throws IOException { + input(); + int answer = kruskal(); + System.out.println(answer); + } + + public static int kruskal() { + int count = 0; + int cost = 0; + + for (int i = 0; i < m; i++) { + int[] road = list.get(i); + + if (count == n-1) { + break; + } + + if (union(road[0], road[1])) { + cost += road[2] + t * count; + count++; + } + } + + return cost; + } + + public static int findParent(int node) { + if (parent[node] != node) { + parent[node] = findParent(parent[node]); + } + return parent[node]; + } + + public static boolean union(int a, int b) { + a = findParent(a); + b = findParent(b); + + if (a == b) { + return false; + } + + if (a < b) { + parent[b] = a; + } else { + parent[a] = b; + } + + return true; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + t = Integer.parseInt(st.nextToken()); + + parent = IntStream.range(0, n+1).toArray(); + list = new ArrayList<>(); + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + list.add(new int[] {a, b, c}); + } + + list.sort((a, b) -> a[2] - b[2]); + } +} From dc3c80710da8067297ad41c0ed49ce36dfb84dc8 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Fri, 11 Nov 2022 14:15:09 +0900 Subject: [PATCH 137/163] =?UTF-8?q?[BOJ-17090-JAVA]=20=EB=AF=B8=EB=A1=9C?= =?UTF-8?q?=20=ED=83=88=EC=B6=9C=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_17090.java | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_17090.java diff --git a/java/BOJ/Gold/III/G3_17090.java b/java/BOJ/Gold/III/G3_17090.java new file mode 100644 index 0000000..605db74 --- /dev/null +++ b/java/BOJ/Gold/III/G3_17090.java @@ -0,0 +1,122 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17090 + * + * ? 제목: 미로 탈출하기 + * ? 시간 제한: 1초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 크기가 N×M인 미로가 있고, 미로는 크기가 1×1인 칸으로 나누어져 있다. 미로의 각 칸에는 문자가 하나 적혀있는데, 적혀있는 문자에 따라서 다른 칸으로 이동할 수 있다. + * 어떤 칸(r, c)에 적힌 문자가 + * + * U인 경우에는 (r-1, c)로 이동해야 한다. + * R인 경우에는 (r, c+1)로 이동해야 한다. + * D인 경우에는 (r+1, c)로 이동해야 한다. + * L인 경우에는 (r, c-1)로 이동해야 한다. + * + * 미로에서 탈출 가능한 칸의 수를 계산해보자. 탈출 가능한 칸이란, 그 칸에서 이동을 시작해서 칸에 적힌대로 이동했을 때, 미로의 경계 밖으로 이동하게 되는 칸을 의미한다. + * + * ? 입력 & 파싱 + * 첫째 줄에 미로의 크기 N, M(3 ≤ N, M ≤ 500)이 주어진다. 둘째 줄부터 N개의 줄에는 미로의 각 칸에 적힌 문자가 주어진다. + * + * 3 3 -> n m + * DDD -> arr[0][0] ~ arr[0][m-1] + * DDD + * DDD -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 첫째 줄에 탈출 가능한 칸의 수를 출력한다. + * + * 9 + * + * ? 채점 결과 + * * 시간: 0.208초 + * * 메모리: 57MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +public class G3_17090 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m; + static char[][] arr; + static boolean[][] visit; + static int[][] answer; + static Map dir; + + public static void main(String[] args) throws IOException { + input(); + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (answer[i][j] == 0) { + visit[i][j] = true; + dfs(i, j); + visit[i][j] = false; + } + } + } + + int count = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (answer[i][j] == 1) { + count++; + } + } + } + + System.out.println(count); + } + + public static int dfs(int x, int y) { + int[] d = dir.get(arr[x][y]); + int nx = x + d[0]; + int ny = y + d[1]; + + if (answer[x][y] != 0) { + return answer[x][y]; + } + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + return answer[x][y] = 1; + } + + if (visit[nx][ny]) { + return answer[x][y] = -1; + } + + visit[nx][ny] = true; + answer[x][y] = dfs(nx, ny); + visit[nx][ny] = false; + + return answer[x][y]; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + visit = new boolean[n][m]; + answer = new int[n][m]; + arr = new char[n][m]; + for (int i = 0; i < n; i++) { + arr[i] = br.readLine().toCharArray(); + } + + dir = new HashMap<>(); + dir.put('D', new int[] {1, 0}); + dir.put('U', new int[] {-1, 0}); + dir.put('L', new int[] {0, -1}); + dir.put('R', new int[] {0, 1}); + } +} From 080293c04e0e9c9b8d3476cdde6c649c50ee24f3 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 12 Nov 2022 14:16:47 +0900 Subject: [PATCH 138/163] =?UTF-8?q?[BOJ-9470-JAVA]=20Strahler=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_9470.java | 129 +++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_9470.java diff --git a/java/BOJ/Gold/III/G3_9470.java b/java/BOJ/Gold/III/G3_9470.java new file mode 100644 index 0000000..ab81414 --- /dev/null +++ b/java/BOJ/Gold/III/G3_9470.java @@ -0,0 +1,129 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/9470 + * + * ? 제목: Strahler 순서 + * ? 시간 제한: 1초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 지질학에서 하천계는 유향그래프로 나타낼 수 있다. 강은 간선으로 나타내며, 물이 흐르는 방향이 간선의 방향이 된다. 노드는 호수나 샘처럼 강이 시작하는 곳, 강이 합쳐지거나 나누어지는 곳, 바다와 만나는 곳이다.* + * 네모 안의 숫자는 순서를 나타내고, 동그라미 안의 숫자는 노드 번호를 나타낸다. + * 하천계의 Strahler 순서는 다음과 같이 구할 수 있다. + * 강의 근원인 노드의 순서는 1이다. + * 나머지 노드는 그 노드로 들어오는 강의 순서 중 가장 큰 값을 i라고 했을 때, 들어오는 모든 강 중에서 Strahler 순서가 i인 강이 1개이면 순서는 i, 2개 이상이면 순서는 i+1이다. + * 하천계의 순서는 바다와 만나는 노드의 순서와 같다. 바다와 만나는 노드는 항상 1개이며, 위의 그림의 Strahler 순서는 3이다. + * 하천계의 정보가 주어졌을 때, Strahler 순서를 구하는 프로그램을 작성하시오.* + * 실제 강 중에서 Strahler 순서가 가장 큰 강은 아마존 강(12)이며, 미국에서 가장 큰 값을 갖는 강은 미시시피 강(10)이다. + * 노드 M은 항상 바다와 만나는 노드이다. + * + * ? 입력 * 파싱 + * 첫째 줄에 테스트 케이스의 수 T (1 ≤ T ≤ 1000)가 주어진다. + * 각 테스트 케이스의 첫째 줄에는 K, M, P가 주어진다. K는 테스트 케이스 번호, M은 노드의 수, P는 간선의 수이다. (2 ≤ M ≤ 1000) 다음 P개 줄에는 간선의 정보를 나타내는 A, B가 주어지며, A에서 B로 물이 흐른다는 뜻이다. (1 ≤ A, B ≤ M) M은 항상 바다와 만나는 노드이며, 밖으로 향하는 간선은 존재하지 않는다. + * + * 1 -> t + * 1 7 8 -> k m p + * 1 3 -> a b + * 2 3 -> a b + * 6 4 -> a b + * 3 4 -> a b + * 3 5 -> a b + * 6 7 -> a b + * 5 7 -> a b + * 4 7 -> a b + * + * ? 출력 + * 각 테스트 케이스마다 테스트 케이스 번호와 입력으로 주어진 하천계의 Strahler 순서를 한 줄에 하나씩 출력한다. + * + * 1 3 + * + * ? 채점 결과 + * * 시간: 0.08초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G3_9470 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int k, m, p; + static int[] degree; + static int[][] strahler; + static ArrayList[] list; + + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); + StringBuffer sb = new StringBuffer(); + for (int c = 1; c <= t; c++) { + input(); + Queue queue = new LinkedList<>(); + for (int i = 1; i <= m; i++) { + if (degree[i] == 0) { + queue.add(i); + strahler[i] = new int[] {1, 1}; + } + } + + while (!queue.isEmpty()) { + int cur = queue.poll(); + + for (int next : list[cur]) { + if (strahler[next][0] == strahler[cur][0]) { + strahler[next][1]++; + } else if (strahler[next][0] < strahler[cur][0]) { + strahler[next] = new int[] {strahler[cur][0], 1}; + } + + if (--degree[next] == 0) { + if (strahler[next][1] > 1) { + strahler[next][0]++; + } + strahler[next][1] = 0; + queue.add(next); + } + }; + } + sb.append(c + " " + strahler[m][0] + "\n"); + } + + + + bw.write(sb.toString()); + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + k = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + p = Integer.parseInt(st.nextToken()); + + strahler = new int[m+1][2]; + degree = new int[m+1]; + list = new ArrayList[m+1]; + for (int i = 1; i <= m; i++) { + list[i] = new ArrayList<>(); + } + + for (int i = 0; i < p; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + list[a].add(b); + degree[b]++; + } + } +} From 387f9460f8160034a0c7d6c6ee55f1dff483de03 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 13 Nov 2022 13:28:08 +0900 Subject: [PATCH 139/163] =?UTF-8?q?[BOJ-11047-JAVA]=20=EB=8F=99=EC=A0=84?= =?UTF-8?q?=200?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/IV/S4_11047.java | 78 ++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 java/BOJ/Silver/IV/S4_11047.java diff --git a/java/BOJ/Silver/IV/S4_11047.java b/java/BOJ/Silver/IV/S4_11047.java new file mode 100644 index 0000000..b7258a3 --- /dev/null +++ b/java/BOJ/Silver/IV/S4_11047.java @@ -0,0 +1,78 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11047 + * + * ? 제목: 동전 0 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 준규가 가지고 있는 동전은 총 N종류이고, 각각의 동전을 매우 많이 가지고 있다. + * 동전을 적절히 사용해서 그 가치의 합을 K로 만들려고 한다. 이때 필요한 동전 개수의 최솟값을 구하는 프로그램을 작성하시오. + * + * ? 입력 + * 첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000) + * 둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수) + * + * 10 4200 -> n k + * 1 -> coin[0] + * 5 + * 10 + * 50 + * 100 + * 500 + * 1000 + * 5000 + * 10000 + * 50000 -> coin[n-1] + * + * ? 출력 + * 첫째 줄에 K원을 만드는데 필요한 동전 개수의 최솟값을 출력한다. + * + * 12 + * + * ? 채점 결과 + * * 시간: 0.076초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.IV; + +import java.io.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.StringTokenizer; + +public class S4_11047 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n, k; + static Integer[] coin; + + public static void main(String[] args) throws IOException { + input(); + int count = 0; + for (int i = 0; i < n; i++) { + int c = k / coin[i]; + count += c; + k -= coin[i] * c; + } + System.out.println(count); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + coin = new Integer[n]; + for (int i = 0; i < n; i++) { + coin[i] = Integer.parseInt(br.readLine()); + } + + Arrays.sort(coin, Collections.reverseOrder()); + } +} From 8d13cbfcb9d75de32ccafbf1706bc724b00e03d7 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 14 Nov 2022 10:07:41 +0900 Subject: [PATCH 140/163] =?UTF-8?q?[BOJ-1541-JAVA]=20=EC=9E=83=EC=96=B4?= =?UTF-8?q?=EB=B2=84=EB=A6=B0=20=EA=B4=84=ED=98=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/II/S2_1541.java | 59 +++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 java/BOJ/Silver/II/S2_1541.java diff --git a/java/BOJ/Silver/II/S2_1541.java b/java/BOJ/Silver/II/S2_1541.java new file mode 100644 index 0000000..4493935 --- /dev/null +++ b/java/BOJ/Silver/II/S2_1541.java @@ -0,0 +1,59 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1541 + * + * ? 제목: 잃어버린 괄호 + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 세준이는 양수와 +, -, 그리고 괄호를 가지고 식을 만들었다. 그리고 나서 세준이는 괄호를 모두 지웠다. + * 그리고 나서 세준이는 괄호를 적절히 쳐서 이 식의 값을 최소로 만들려고 한다. + * 괄호를 적절히 쳐서 이 식의 값을 최소로 만드는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다 많이 연속되는 숫자는 없다. 수는 0으로 시작할 수 있다. 입력으로 주어지는 식의 길이는 50보다 작거나 같다. + * + * 55-50+40 -> str + * + * ? 출력 + * 첫째 줄에 정답을 출력한다. + * + * 35 + * + * ? 채점 결과 + * * 시간: 0.088초 + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.II; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class S2_1541 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static void main(String[] args) throws IOException { + String str = br.readLine(); + String[] substracts = str.split("-"); + int total = 0; + for (int i = 0; i < substracts.length; i++) { + String[] sums = substracts[i].split("\\+"); + int sum = 0; + for (String s : sums) { + sum += Integer.parseInt(s); + } + + if (i == 0) { + total += sum; + } else { + total -= sum; + } + } + + System.out.println(total); + } +} From 9ae002207cada4f3448253c5a877818e42c0b572 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 15 Nov 2022 14:18:54 +0900 Subject: [PATCH 141/163] =?UTF-8?q?[BOJ-13305-JAVA]=20=EC=A3=BC=EC=9C=A0?= =?UTF-8?q?=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/III/S3_13305.java | 84 +++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 java/BOJ/Silver/III/S3_13305.java diff --git a/java/BOJ/Silver/III/S3_13305.java b/java/BOJ/Silver/III/S3_13305.java new file mode 100644 index 0000000..fc5a148 --- /dev/null +++ b/java/BOJ/Silver/III/S3_13305.java @@ -0,0 +1,84 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/13305 + * + * ? 제목: 주유소 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * 어떤 나라에 N개의 도시가 있다. 이 도시들은 일직선 도로 위에 있다. 편의상 일직선을 수평 방향으로 두자. 제일 왼쪽의 도시에서 제일 오른쪽의 도시로 자동차를 이용하여 이동하려고 한다. 인접한 두 도시 사이의 도로들은 서로 길이가 다를 수 있다. 도로 길이의 단위는 km를 사용한다. + * 처음 출발할 때 자동차에는 기름이 없어서 주유소에서 기름을 넣고 출발하여야 한다. 기름통의 크기는 무제한이어서 얼마든지 많은 기름을 넣을 수 있다. 도로를 이용하여 이동할 때 1km마다 1리터의 기름을 사용한다. 각 도시에는 단 하나의 주유소가 있으며, 도시 마다 주유소의 리터당 가격은 다를 수 있다. 가격의 단위는 원을 사용한다. + * 예를 들어, 이 나라에 다음 그림처럼 4개의 도시가 있다고 하자. 원 안에 있는 숫자는 그 도시에 있는 주유소의 리터당 가격이다. 도로 위에 있는 숫자는 도로의 길이를 표시한 것이다. + * 제일 왼쪽 도시에서 6리터의 기름을 넣고, 더 이상의 주유 없이 제일 오른쪽 도시까지 이동하면 총 비용은 30원이다. 만약 제일 왼쪽 도시에서 2리터의 기름을 넣고(2×5 = 10원) 다음 번 도시까지 이동한 후 3리터의 기름을 넣고(3×2 = 6원) 다음 도시에서 1리터의 기름을 넣어(1×4 = 4원) 제일 오른쪽 도시로 이동하면, 총 비용은 20원이다. 또 다른 방법으로 제일 왼쪽 도시에서 2리터의 기름을 넣고(2×5 = 10원) 다음 번 도시까지 이동한 후 4리터의 기름을 넣고(4×2 = 8원) 제일 오른쪽 도시까지 이동하면, 총 비용은 18원이다. + * 각 도시에 있는 주유소의 기름 가격과, 각 도시를 연결하는 도로의 길이를 입력으로 받아 제일 왼쪽 도시에서 제일 오른쪽 도시로 이동하는 최소의 비용을 계산하는 프로그램을 작성하시오. + * + * ? 입력 + * 표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에는 도시의 개수를 나타내는 정수 N(2 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 인접한 두 도시를 연결하는 도로의 길이가 제일 왼쪽 도로부터 N-1개의 자연수로 주어진다. 다음 줄에는 주유소의 리터당 가격이 제일 왼쪽 도시부터 순서대로 N개의 자연수로 주어진다. 제일 왼쪽 도시부터 제일 오른쪽 도시까지의 거리는 1이상 1,000,000,000 이하의 자연수이다. 리터당 가격은 1 이상 1,000,000,000 이하의 자연수이다. + * + * 4 -> n + * 2 3 1 -> len[1] ~ len[n-1] + * 5 2 4 1 -> gas[0] ~ gas[n-1] + * + * ? 출력 + * 표준 출력으로 제일 왼쪽 도시에서 제일 오른쪽 도시로 가는 최소 비용을 출력한다. + * + * ? 채점 결과 + * * 시간: 0.38초 + * * 메모리: 40MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Silver.III; + +import java.io.*; +import java.util.StringTokenizer; + +public class S3_13305 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n; + static int[] len; + static int[] gas; + + public static void main(String[] args) throws IOException { + input(); + + long cost = 0; + int cur = 0; + + while (cur < n-1) { + int canGo = 0; + int next = cur; + for (int i = cur+1; i < n; i++) { + canGo += len[i]; + next = i; + if (gas[cur] > gas[i]) { + break; + } + } + + cost += (long) gas[cur] * canGo; + cur = next; + } + + System.out.println(cost); + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + len = new int[n]; + gas = new int[n]; + + st = new StringTokenizer(br.readLine()); + for (int i = 1; i < n; i++) { + len[i] = Integer.parseInt(st.nextToken()); + } + + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + gas[i] = Integer.parseInt(st.nextToken()); + } + } +} From de0fc111ca0776334c362681eac7ac6dbf9d5ce1 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Wed, 16 Nov 2022 08:39:13 +0900 Subject: [PATCH 142/163] =?UTF-8?q?[BOJ-16437-JAVA]=20=EC=96=91=20?= =?UTF-8?q?=EA=B5=AC=EC=B6=9C=20=EC=9E=91=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_16437.java | 119 ++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_16437.java diff --git a/java/BOJ/Gold/III/G3_16437.java b/java/BOJ/Gold/III/G3_16437.java new file mode 100644 index 0000000..abef194 --- /dev/null +++ b/java/BOJ/Gold/III/G3_16437.java @@ -0,0 +1,119 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16437 + * + * ? 제목: 양 구출 작전 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * N개의 섬으로 이루어진 나라가 있습니다. 섬들은 1번 섬부터 N번 섬까지 있습니다. + * 1번 섬에는 구명보트만 있고 다른 섬에는 양들 또는 늑대들이 살고 있습니다. + * 늘어나는 늑대의 개체 수를 감당할 수 없던 양들은 구명보트를 타고 늑대가 없는 나라로 이주하기로 했습니다. + * 각 섬에서 1번 섬으로 가는 경로는 유일하며 i번 섬에는 pi번 섬으로 가는 다리가 있습니다. + * 양들은 1번 섬으로 가는 경로로 이동하며 늑대들은 원래 있는 섬에서 움직이지 않고 섬으로 들어온 양들을 잡아먹습니다. 늑대는 날렵하기 때문에 섬에 들어온 양을 항상 잡을 수 있습니다. 그리고 늑대 한 마리는 최대 한 마리의 양만 잡아먹습니다. + * 얼마나 많은 양이 1번 섬에 도달할 수 있을까요? + * + * ? 입력 & 파싱 + * 첫 번째 줄에 섬의 개수 N (2 ≤ N ≤ 123,456) 이 주어집니다. + * 두 번째 줄부터 N-1개에 줄에 2번 섬부터 N번 섬까지 섬의 정보를 나타내는 ti, ai, pi (1 ≤ ai ≤ 109, 1 ≤ pi ≤ N) 가 주어집니다. + * ti가 'W' 인 경우 i번 섬에 늑대가 ai마리가 살고 있음을, ti가 'S'인 경우 i번 섬에 양이 ai마리가 살고 있음을 의미합니다. pi는 i번째 섬에서 pi번 섬으로 갈 수 있는 다리가 있음을 의미합니다. + * + * 4 -> n + * S 100 3 -> sw c next + * W 50 1 -> sw c next + * S 10 1 -> sw c next + * + * ? 출력 + * 첫 번째 줄에 구출할 수 있는 양의 수를 출력합니다. + * + * 60 + * + * ? 채점 결과 + * * 시간: 0.436초 + * * 메모리: 61MB + * * 언어: JAVA8 + * * 시도: 2 + */ +package Gold.III; + +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 G3_16437 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n; + static int[] degree; + static int[] adj; + static long[][] arr; + + public static void main(String[] args) throws IOException { + input(); + topologicalSort(); + System.out.println(arr[1][0]); + } + + public static void topologicalSort() { + Queue queue = new LinkedList<>(); + for (int i = 1; i <= n; i++) { + if (degree[i] == 0) { + queue.add(i); + } + } + + while (!queue.isEmpty()) { + int cur = queue.poll(); + + if (cur == 1) { + break; + } + + int next = adj[cur]; + + if (arr[cur][0] != 0) { + if (arr[next][1] < arr[cur][0]) { + arr[next][0] += (arr[cur][0] - arr[next][1]); + arr[next][1] = 0; + arr[cur][0] = 0; + } else { + arr[next][1] -= arr[cur][0]; + arr[cur][0] = 0; + } + } + + + if (--degree[next] == 0) { + queue.add(next); + } + } + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + degree = new int[n + 1]; + adj = new int[n + 1]; + arr = new long[n + 1][2]; + + for (int i = 2; i <= n; i++) { + st = new StringTokenizer(br.readLine()); + String sw = st.nextToken(); + int c = Integer.parseInt(st.nextToken()); + int next = Integer.parseInt(st.nextToken()); + + if (sw.equals("S")) { + arr[i][0] = c; + } else { + arr[i][1] = c; + } + adj[i] = next; + degree[next]++; + } + + } +} From 9e0c684f205606dc60395126ae948892d38fb344 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 17 Nov 2022 13:26:30 +0900 Subject: [PATCH 143/163] =?UTF-8?q?[BOJ-1946-JAVA]=20=EC=8B=A0=EC=9E=85=20?= =?UTF-8?q?=EC=82=AC=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_1946.java | 92 ++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_1946.java diff --git a/java/BOJ/Silver/I/S1_1946.java b/java/BOJ/Silver/I/S1_1946.java new file mode 100644 index 0000000..3b3725c --- /dev/null +++ b/java/BOJ/Silver/I/S1_1946.java @@ -0,0 +1,92 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/1946 + * + * ? 제목: 신입 사원 + * ? 시간 제한: 2초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 언제나 최고만을 지향하는 굴지의 대기업 진영 주식회사가 신규 사원 채용을 실시한다. 인재 선발 시험은 1차 서류심사와 2차 면접시험으로 이루어진다. 최고만을 지향한다는 기업의 이념에 따라 그들은 최고의 인재들만을 사원으로 선발하고 싶어 한다. + * 그래서 진영 주식회사는, 다른 모든 지원자와 비교했을 때 서류심사 성적과 면접시험 성적 중 적어도 하나가 다른 지원자보다 떨어지지 않는 자만 선발한다는 원칙을 세웠다. 즉, 어떤 지원자 A의 성적이 다른 어떤 지원자 B의 성적에 비해 서류 심사 결과와 면접 성적이 모두 떨어진다면 A는 결코 선발되지 않는다. + * 이러한 조건을 만족시키면서, 진영 주식회사가 이번 신규 사원 채용에서 선발할 수 있는 신입사원의 최대 인원수를 구하는 프로그램을 작성하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에는 테스트 케이스의 개수 T(1 ≤ T ≤ 20)가 주어진다. 각 테스트 케이스의 첫째 줄에 지원자의 숫자 N(1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개 줄에는 각각의 지원자의 서류심사 성적, 면접 성적의 순위가 공백을 사이에 두고 한 줄에 주어진다. 두 성적 순위는 모두 1위부터 N위까지 동석차 없이 결정된다고 가정한다. + * + * 2 -> t + * 5 -> n + * 3 2 -> arr[3] = 2 + * 1 4 -> arr[1] = 4 + * 4 1 ... + * 2 3 + * 5 5 -> arr[5] = 5; + * 7 -> n + * 3 6 -> ... + * 7 3 + * 4 2 + * 1 4 + * 5 7 + * 2 5 + * 6 1 + * + * ? 출력 + * 각 테스트 케이스에 대해서 진영 주식회사가 선발할 수 있는 신입사원의 최대 인원수를 한 줄에 하나씩 출력한다. + * + * 4 + * 3 + * + * ? 채점 결과 + * * 시간: 0.828초 + * * 메모리: 295MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.*; +import java.util.StringTokenizer; + +public class S1_1946 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n; + static int[] arr; + + public static void main(String[] args) throws IOException { + StringBuffer sb = new StringBuffer(); + + int t = Integer.parseInt(br.readLine()); + for (int i = 0; i < t; i++) { + input(); + + int bMax = arr[1]; + int count = 1; + for (int j = 2; j <= n; j++) { + if (bMax > arr[j]) { + bMax = arr[j]; + count++; + } + } + + sb.append(count + "\n"); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void input() throws IOException { + n = Integer.parseInt(br.readLine()); + arr = new int[n + 1]; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + arr[Integer.parseInt(st.nextToken())] = Integer.parseInt(st.nextToken()); + } + } +} From 51e1b717d2acb58abbcb5ef30a9bf9a5de76e1be Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 18 Nov 2022 17:12:47 +0900 Subject: [PATCH 144/163] =?UTF-8?q?[BOJ-10711-JAVA]=20=EB=AA=A8=EB=9E=98?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_10711.java | 121 +++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_10711.java diff --git a/java/BOJ/Gold/II/G2_10711.java b/java/BOJ/Gold/II/G2_10711.java new file mode 100644 index 0000000..b663d48 --- /dev/null +++ b/java/BOJ/Gold/II/G2_10711.java @@ -0,0 +1,121 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/10711 + * + * ? 제목: 모래성 + * ? 시간 제한: 1초 + * ? 메모리 제한: 256MB + * + * ? 문제 + * 명우와 친구들은 여름방학을 맞이하여 해변가에 놀러가기로 했다. 이번에 여행을 떠난 해수욕장의 이름은 ALPS(Awsome Land & Poor Sea)이다. + * 해변가에서 수영복을 입은 미녀들에게 관심이 많은 원철이와는 달리 명우는 해변가의 모래에 더 관심이 많다. 해변가의 모래는 무한한 것들을 만들 수 있는 가능성을 내포하고 있다. 또한 이렇게 만들어진 작품이 파도에 의해 사라지는 모습은, 마치 자신이 가장 빛날 수 있는 시간을 알고 스스로 아름답게 산화하려는 것으로 보인다. 이런 완벽에 가까운 물품인 모래를 두고서 해수욕이나 헤엄을 치는 것은 인생을 낭비하는 것과 같다고 생각한다. 하지만 아무도 명우의 말에 공감해주지 못했고, 결국 명우는 혼자서 모래성을 만들었다. + * + * 다른 친구들이 혼신의 힘을 다해 놀고있을 때 명우는 혼신의 힘을 다해 모래성을 쌓았다. 이 모래성은 언젠간 파도에 의해서 무너질 터... 명우는 이런 무너짐도 예술의 일환으로 이해한 사람이므로 무너지는 것도 고려해서 모래성을 만들었다. + * + * 그가 만든 모래성을 2차원 격자단위로 만들었으며, 각 격자마다 튼튼함의 정도를 다르게 해서 성을 만들었다. 이 튼튼함은 1부터 9 사이의 숫자로 표현될 수 있다. 이 튼튼함은, 자기 격자 주변의 8방향 (위 아래 왼쪽 오른쪽, 그리고 대각선) 을 봐서 모래성이 쌓여있지 않은 부분의 개수가 자기 모래성의 튼튼함보다 많거나 같은 경우 파도에 의해서 무너질 수 있음을 의미한다. 그 이외의 경우는 파도가 쳐도 무너지지 않는다. 모래성이 무너진 경우, 그 격자는 모래성이 쌓여있지 않은 것으로 취급한다. + * + * 이 모래성은 언젠가는 파도에 의해서 깎이고 깎여서, 결국 한가지 형태로 수렴할 것이다. 모래성을 완성한 명우는 문득 자신이 만든 예술품의 수명이 궁금해졌다. 모래성은 위에 서술한 바와 같이 파도가 한번 칠 때마다 특정 부분이 무너저내리는 방식으로 모양이 변화된다. 모래성이 더이상 모양이 변하지 않게 되려면 (모양이 수렴되려면) 파도가 몇번 쳐야하는지 구해보자. + * + * ? 입력 & 파싱 + * 첫째 줄에는 모래성의 가로세로 격자 크기 H, W가 주어진다. (1 ≤ H, W ≤ 1,000) + * 그 다음 H줄에 걸쳐 W개의 문자로 모래성의 상태를 나타내는 문자가 들어온다. + * 각 문자는 1~9 사이의 숫자, 또는 '.' 이다. 1~9는 그 격자의 모래의 강도를 나타내며, '.'는 모래가 없다는 뜻이다. + * 모래성은 격자의 가장자리와 접해 있지 않다. + * + * 5 6 -> h w + * ...... -> arr[0][0] ~ arr[0][w-1] + * .939.. + * .3428. + * .9393. + * ...... -> arr[h-1][0] ~ arr[h-1][w-1] + * + * ? 출력 + * 몇번의 파도가 몰려오고나서야 모래성의 상태가 수렴하는지를 구한다. + * + * 3 + * + * ? 채점 결과 + * * 시간: 0.388초 + * * 메모리: 70MB + * * 언어: JAVA8 + * * 시도: 3 + */ +package Gold.II; + +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 G2_10711 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int h, w; + static char[][] arr; + static Queue queue; + + public static void main(String[] args) throws IOException { + input(); + + int time = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + + for (int i = 0; i < size; i++) { + int[] cur = queue.poll(); + + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + if (dx == 0 && dy == 0) { + continue; + } + + int nx = cur[0] + dx; + int ny = cur[1] +dy; + + if (nx < 0 || ny < 0 || nx >= h || ny >= w) { + continue; + } + + if (arr[nx][ny] == '.') { + continue; + } + + if (--arr[nx][ny] == '0') { + arr[nx][ny] = '.'; + queue.add(new int[] {nx, ny}); + } + } + } + } + + if (!queue.isEmpty()) { + time++; + } + } + + System.out.println(time); + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + h = Integer.parseInt(st.nextToken()); + w = Integer.parseInt(st.nextToken()); + + queue = new LinkedList<>(); + arr = new char[h][w]; + + for (int i = 0; i < h; i++) { + char[] sands = br.readLine().toCharArray(); + for (int j = 0; j < w; j++) { + arr[i][j] = sands[j]; + if (arr[i][j] == '.') { + queue.add(new int[] {i, j}); + } + } + } + } +} From 5566fe87b94645b4024757202d1adf7016887ef1 Mon Sep 17 00:00:00 2001 From: dongjji Date: Sat, 19 Nov 2022 12:17:31 +0900 Subject: [PATCH 145/163] =?UTF-8?q?[BOJ-1439-JAVA]=20=EB=92=A4=EC=A7=91?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/V/S5_1439.java | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 java/BOJ/Silver/V/S5_1439.java diff --git a/java/BOJ/Silver/V/S5_1439.java b/java/BOJ/Silver/V/S5_1439.java new file mode 100644 index 0000000..165a844 --- /dev/null +++ b/java/BOJ/Silver/V/S5_1439.java @@ -0,0 +1,55 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * 다솜이는 0과 1로만 이루어진 문자열 S를 가지고 있다. 다솜이는 이 문자열 S에 있는 모든 숫자를 전부 같게 만들려고 한다. 다솜이가 할 수 있는 행동은 S에서 연속된 하나 이상의 숫자를 잡고 모두 뒤집는 것이다. 뒤집는 것은 1을 0으로, 0을 1로 바꾸는 것을 의미한다. + * 예를 들어 S=0001100 일 때, + * 전체를 뒤집으면 1110011이 된다. + * 4번째 문자부터 5번째 문자까지 뒤집으면 1111111이 되어서 2번 만에 모두 같은 숫자로 만들 수 있다. + * 하지만, 처음부터 4번째 문자부터 5번째 문자까지 문자를 뒤집으면 한 번에 0000000이 되어서 1번 만에 모두 같은 숫자로 만들 수 있다. + * 문자열 S가 주어졌을 때, 다솜이가 해야하는 행동의 최소 횟수를 출력하시오. + * + * ? 입력 & 파싱 + * 첫째 줄에 문자열 S가 주어진다. S의 길이는 100만보다 작다. + * + * 0001100 -> arr + * + * ? 출력 + * 첫째 줄에 다솜이가 해야하는 행동의 최소 횟수를 출력한다. + * + * 1 + * + * ? 채점 결과 + * * 시간: 0.076ms + * * 메모리: 11MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.V; + +import java.io.*; +import java.util.StringTokenizer; + +public class S5_1439 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + public static void main(String[] args) throws IOException { + char[] arr = br.readLine().toCharArray(); + int[] count = new int[2]; + + int before = -1; + for (int i = 0; i < arr.length; i++) { + int cur = arr[i] - '0'; + if (cur != before) { + before = cur; + count[cur]++; + } + } + + System.out.println(Math.min(count[0], count[1])); + } +} From f4718311f5b7e0092386074ede98d4691ab3d8ae Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 20 Nov 2022 14:01:45 +0900 Subject: [PATCH 146/163] =?UTF-8?q?[BOJ-16932-JAVA]=20=EB=AA=A8=EC=96=91?= =?UTF-8?q?=20=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/III/G3_16932.java | 145 ++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_16932.java diff --git a/java/BOJ/Gold/III/G3_16932.java b/java/BOJ/Gold/III/G3_16932.java new file mode 100644 index 0000000..f59e46f --- /dev/null +++ b/java/BOJ/Gold/III/G3_16932.java @@ -0,0 +1,145 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16932 + * + * ? 제목: 모양 만들기 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 문제 + * N×M인 배열에서 모양을 찾으려고 한다. 배열의 각 칸에는 0과 1 중의 하나가 들어있다. 두 칸이 서로 변을 공유할때, 두 칸을 인접하다고 한다. + * 1이 들어 있는 인접한 칸끼리 연결했을 때, 각각의 연결 요소를 모양이라고 부르자. 모양의 크기는 모양에 포함되어 있는 1의 개수이다. + * 배열의 칸 하나에 들어있는 수를 변경해서 만들 수 있는 모양의 최대 크기를 구해보자. + * + * ? 입력 + * 첫째 줄에 배열의 크기 N과 M이 주어진다. 둘째 줄부터 N개의 줄에는 배열에 들어있는 수가 주어진다. + * + * 3 3 -> n m + * 0 1 1 -> arr[0][0] ~ arr[0][m-1] + * 0 0 1 + * 0 1 0 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 첫째 줄에 수 하나를 변경해서 만들 수 있는 모양의 최대 크기를 출력한다. + * + * 5 + * + * ? 제한 + * 2 ≤ N, M ≤ 1,000 + * 0과 1의 개수는 하나 이상이다. + * + * ? 채점 결과 + * * 시간: 3.452초 + * * 메모리: 209MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.*; + +public class G3_16932 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n, m; + static int[][] arr, groupNum; + static boolean[][] visit; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + static int[] group; + static int num; + + public static void main(String[] args) throws IOException { + input(); + int max = 0; + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (arr[i][j] == 1 && !visit[i][j]) { + num++; + visit[i][j] = true; + groupNum[i][j] = num; + group[num] = 1; + dfs(i, j); + } + } + } + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (arr[i][j] == 0) { + int count = 0; + Set set = new HashSet<>(); + for (int k = 0; k < 4; k++) { + int nx = i + dx[k]; + int ny = j + dy[k]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + continue; + } + + if (groupNum[nx][ny] != 0) { + set.add(groupNum[nx][ny]); + } + } + + for (int g : set) { + count += group[g]; + } + + max = Math.max(max, count); + } + } + } + + System.out.println(max+1); + } + + public static void dfs(int x, int y) { + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m || visit[nx][ny]) { + continue; + } + + if (arr[nx][ny] == 1) { + visit[nx][ny] = true; + groupNum[nx][ny] = num; + group[num]++; + dfs(nx, ny); + } + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n][m]; + visit = new boolean[n][m]; + groupNum = new int[n][m]; + + num = 0; + + int count = 0; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + if (arr[i][j] == 1) { + count++; + } + } + } + + group = new int[count+1]; + } +} From 800e71c158cd12de3ba98b17916bcd8f43a7621b Mon Sep 17 00:00:00 2001 From: ing9990 Date: Fri, 6 Jan 2023 13:31:37 +0900 Subject: [PATCH 147/163] =?UTF-8?q?[=ED=94=84=EB=A1=9C=EA=B7=B8=EB=9E=98?= =?UTF-8?q?=EB=A8=B8=EC=8A=A4-142085-Java]=20=EB=94=94=ED=8E=9C=EC=8A=A4?= =?UTF-8?q?=EA=B2=8C=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\354\212\244\352\262\214\354\236\204.java" | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 "java/Programmers/Level2/\353\224\224\355\216\234\354\212\244\352\262\214\354\236\204.java" diff --git "a/java/Programmers/Level2/\353\224\224\355\216\234\354\212\244\352\262\214\354\236\204.java" "b/java/Programmers/Level2/\353\224\224\355\216\234\354\212\244\352\262\214\354\236\204.java" new file mode 100644 index 0000000..ee18b78 --- /dev/null +++ "b/java/Programmers/Level2/\353\224\224\355\216\234\354\212\244\352\262\214\354\236\204.java" @@ -0,0 +1,88 @@ +import java.util.*; + +/** + * 문제링크 : https://school.programmers.co.kr/learn/courses/30/lessons/142085 + * + * 입력예시 + * n = 7 + * k = 3 + * enemy = [4, 2, 4, 5, 3, 3, 1] + * + * 결과예시 + * 5 + */ + +class Solution { + public int solution(int n, int k, int[] enemy) { + + // 적의 가장 적은 병력을 효율적으로 찾기 위해 우선순위큐를 선언합니다. + int answer = 0; + Queue heap = new PriorityQueue<>(); + + // "무적권"의 갯수 만큼 큐를 채워줍니다. + for (int i = 0; i < k; i++, answer++) { + if (i >= enemy.length) { + break; + } + heap.offer(enemy[i]); + } + + // 무적권이 없을 경우 나의 병력이 0 미만일때 까지 라운드를 진행합니다. + if (heap.size() == 0) { + for (int i : enemy) { + if (n - i > 0) { + answer++; + n -= i; + } + } + } else { // 적의 가장 적은 병력 수가 나의 병력보다 클때의 라운드 수가 정답입니다. + for (int i = k; i < enemy.length; i++, answer++) { + heap.offer(enemy[i]); + int minValue = heap.poll(); + + if (n < minValue) { + break; + } + + n -= minValue; + } + } + return answer; + } +} + + +/* +테스트 1 〉 통과 (1.47ms, 79.6MB) +테스트 2 〉 통과 (6.75ms, 95MB) +테스트 3 〉 통과 (84.87ms, 136MB) +테스트 4 〉 통과 (4.96ms, 124MB) +테스트 5 〉 통과 (2.80ms, 79.6MB) +테스트 6 〉 통과 (93.06ms, 145MB) +테스트 7 〉 통과 (76.02ms, 142MB) +테스트 8 〉 통과 (33.14ms, 135MB) +테스트 9 〉 통과 (51.91ms, 126MB) +테스트 10 〉 통과 (142.13ms, 138MB) +테스트 11 〉 통과 (0.54ms, 122MB) +테스트 12 〉 통과 (0.88ms, 126MB) +테스트 13 〉 통과 (0.28ms, 78.3MB) +테스트 14 〉 통과 (0.42ms, 79MB) +테스트 15 〉 통과 (0.36ms, 67.5MB) +테스트 16 〉 통과 (0.33ms, 81.8MB) +테스트 17 〉 통과 (0.32ms, 73.5MB) +테스트 18 〉 통과 (0.30ms, 75.7MB) +테스트 19 〉 통과 (0.28ms, 74.9MB) +테스트 20 〉 통과 (0.32ms, 77.7MB) +테스트 21 〉 통과 (0.28ms, 74.8MB) +테스트 22 〉 통과 (0.46ms, 74.1MB) +테스트 23 〉 통과 (0.69ms, 77.9MB) +테스트 24 〉 통과 (0.71ms, 78.6MB) +테스트 25 〉 통과 (0.58ms, 72.7MB) +테스트 26 〉 통과 (0.66ms, 76.8MB) +테스트 27 〉 통과 (0.89ms, 76.1MB) +테스트 28 〉 통과 (0.54ms, 80.5MB) +테스트 29 〉 통과 (0.91ms, 81.4MB) +테스트 30 〉 통과 (0.76ms, 77.6MB) +테스트 31 〉 통과 (0.59ms, 77.4MB) +테스트 32 〉 통과 (0.91ms, 85.4MB) + */ \ No newline at end of file From 6e2feeeab8719475d17fb7909bcdbeb0f37455a2 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 8 Jan 2023 13:17:46 +0900 Subject: [PATCH 148/163] =?UTF-8?q?[BOJ-1189-JAVA]=20=EC=BB=B4=EB=B0=B1?= =?UTF-8?q?=ED=99=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Silver/I/S1_1189.java | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 java/BOJ/Silver/I/S1_1189.java diff --git a/java/BOJ/Silver/I/S1_1189.java b/java/BOJ/Silver/I/S1_1189.java new file mode 100644 index 0000000..d233dc6 --- /dev/null +++ b/java/BOJ/Silver/I/S1_1189.java @@ -0,0 +1,102 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * https://www.acmicpc.net/problem/1189 + * + * ? 시간 제한: 2초 + * ? 메모리 제한: 128MB + * + * ? 문제 + * ? 한수는 캠프를 마치고 집에 돌아가려 한다. 한수는 현재 왼쪽 아래점에 있고 집은 오른쪽 위에 있다. 그리고 한수는 집에 돌아가는 방법이 다양하다. 단, 한수는 똑똑하여 한번 지나친 곳을 다시 방문하지는 않는다. + * + * cdef ...f ..ef ..gh cdeh cdej ...f + * bT.. .T.e .Td. .Tfe bTfg bTfi .Tde + * a... abcd abc. abcd a... a.gh abc. + * 거리 : 6 6 6 8 8 10 6 + * + * 위 예제는 한수가 집에 돌아갈 수 있는 모든 경우를 나타낸 것이다. T로 표시된 부분은 가지 못하는 부분이다. 문제는 R x C 맵에 못가는 부분이 주어지고 거리 K가 주어지면 한수가 집까지도 도착하는 경우 중 거리가 K인 가짓수를 구하는 것이다. + * + * ? 입력 + * 첫 줄에 정수 R(1 ≤ R ≤ 5), C(1 ≤ C ≤ 5), K(1 ≤ K ≤ R×C)가 공백으로 구분되어 주어진다. 두 번째부터 R+1번째 줄까지는 R×C 맵의 정보를 나타내는 '.'과 'T'로 구성된 길이가 C인 문자열이 주어진다. + * + * 3 4 6 -> r c k + * .... -> arr[0][0] ~ arr[0][c-1] + * .T.. + * .... -> arr[r-1][0] ~ arr[r-1][c-1] + * + * ? 출력 + * 첫 줄에 거리가 K인 가짓수를 출력한다. + * + * 4 + * + * ? 채점 결과 + * * 시간: 0.096초 + * * 메모리: 12MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Silver.I; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class S1_1189 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int r, c, k; + static int count = 0; + + static char[][] arr; + static boolean[][] visit; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + + visit[r-1][0] = true; + dfs(r-1, 0, 1); + + System.out.println(count); + } + + public static void dfs(int x, int y, int len) { + if (x == 0 && y == c-1) { + if (len == k) { + count++; + } + return; + } + + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (nx < 0 || ny < 0 || nx >= r || ny >= c || visit[nx][ny] || arr[nx][ny] == 'T') { + continue; + } + + visit[nx][ny] = true; + dfs(nx, ny, len+1); + visit[nx][ny] = false; + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + + r = Integer.parseInt(st.nextToken()); + c = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + + arr = new char[r][c]; + visit = new boolean[r][c]; + + for (int i = 0; i < r; i++) { + arr[i] = br.readLine().toCharArray(); + } + } +} From 5a9cb085906298009d2193fa5c8c7d930c8cade9 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sat, 14 Jan 2023 23:31:51 +0900 Subject: [PATCH 149/163] [BOJ-16988-JAVA] Baaaaaaaaaduk2 (Easy) --- java/BOJ/Gold/III/G3_16988.java | 144 ++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_16988.java diff --git a/java/BOJ/Gold/III/G3_16988.java b/java/BOJ/Gold/III/G3_16988.java new file mode 100644 index 0000000..8b49371 --- /dev/null +++ b/java/BOJ/Gold/III/G3_16988.java @@ -0,0 +1,144 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16988 + * + * ? 제목: 링크 참조 + * ? 시간 제한: 2초 + * ? 메모리 제한: 512MB + * + * ? 입력 + * 첫째 줄에 바둑판의 행의 갯수와 열의 갯수를 나타내는 N(3 ≤ N ≤ 20)과 M(3 ≤ M ≤ 20)이 한 칸의 빈칸을 사이에 두고 주어진다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을 나타내는 M개의 정수가 한 개의 빈 칸을 사이에 두고 주어진다. 각 칸에 들어가는 값은 0, 1, 2이다. 0은 빈 칸, 1은 나의 돌, 2는 상대의 돌을 의미한다. 빈 칸이 2개 이상 존재함과 현재 바둑판에서 양 플레이어 모두 상대방의 돌로 빈틈없이 에워싸인 그룹이 없음이 모두 보장된다. + * + * 3 4 -> n m + * 2 0 0 0 -> arr[0][0] ~ arr[0][m-1] + * 0 0 0 0 + * 0 0 0 2 -> arr[n-1][0] ~ arr[n-1][m-1] + * + * ? 출력 + * 첫째 줄에 현재 판에서 돌 2개를 두어 죽일 수 있는 상대 돌의 최대 갯수를 출력한다. + * + * 1 + * + * ? 채점 결과 + * * 시간: 0.476초 + * * 메모리: 222MB + * * 언어: JAVA8 + * * 시도: 1 + */ +package Gold.III; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G3_16988 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n, m; + static int max = 0; + static int total = 0; + + static int count; + static int[][] arr; + static boolean[][] visit; + static ArrayList list; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + for (int i = 0; i < list.size()-1; i++) { + for (int j = i+1; j < list.size(); j++) { + arr[list.get(i)[0]][list.get(i)[1]] = 1; + arr[list.get(j)[0]][list.get(j)[1]] = 1; + + count = 0; + visit = new boolean[n][m]; + + for (int a = 0; a < n; a++) { + for (int b = 0; b < m; b++) { + if (arr[a][b] == 2 && !visit[a][b]) { + total = 0; + bfs(a, b); + } + } + } + + max = Math.max(max, count); + + arr[list.get(i)[0]][list.get(i)[1]] = 0; + arr[list.get(j)[0]][list.get(j)[1]] = 0; + } + } + + bw.write(String.valueOf(max)); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void bfs(int x, int y) { + visit[x][y] = true; + + Queue queue = new LinkedList<>(); + queue.add(new int[] {x, y}); + boolean hasBlank = false; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (arr[cur[0]][cur[1]] == 2) { + total++; + } + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m || visit[nx][ny] || arr[nx][ny] == 1) { + continue; + } + + if (arr[nx][ny] == 0) { + hasBlank = true; + continue; + } + + if (arr[nx][ny] == 2 && !visit[nx][ny]) { + visit[nx][ny] = true; + queue.add(new int[] {nx, ny}); + } + } + } + + + if (!hasBlank) { + count += total; + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + list = new ArrayList<>(); + + arr = new int[n][m]; + for (int i = 0; i < n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + if (arr[i][j] == 0) { + list.add(new int[] {i, j}); + } + } + } + } +} From 836d986e29f7a3e64164b3848482e0876fe58753 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Thu, 19 Jan 2023 16:30:37 +0900 Subject: [PATCH 150/163] =?UTF-8?q?[BOJ-16973-JAVA]=20=EC=A7=81=EC=82=AC?= =?UTF-8?q?=EA=B0=81=ED=98=95=20=ED=83=88=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_16973.java | 137 +++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_16973.java diff --git a/java/BOJ/Gold/IV/G4_16973.java b/java/BOJ/Gold/IV/G4_16973.java new file mode 100644 index 0000000..c588c1d --- /dev/null +++ b/java/BOJ/Gold/IV/G4_16973.java @@ -0,0 +1,137 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/16973 + * + * ? 채점 결과 + * ? 시간: 1.292초 / 2초 + * ? 메모리: 126MB / 512MB + * ? 시도: 1 + */ +package Gold.IV; + +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 G4_16973 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m, h, w, sx, sy, fx, fy; + + // 하, 상, 우, 좌 + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + static int[][] visit; + static int[][] arr; + + public static void main(String[] args) throws IOException { + input(); + System.out.println(bfs()); + } + + public static int bfs() { + visit[sx][sy] = 1; + Queue queue = new LinkedList<>(); + queue.add(new int[] {sx, sy}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == fx && cur[1] == fy) { + return visit[fx][fy]-1; + } + + // 아래로 내려갈 때: 맨 아랫줄에 제한 없어야 함 + if (cur[0]+h <= n && visit[cur[0]+1][cur[1]] == 0) { + down: + for (int i = 0; i < w; i++) { + if (arr[cur[0] + h][cur[1] + i] == 1) { + break down; + } + + if (i == w-1) { + visit[cur[0]+1][cur[1]] = visit[cur[0]][cur[1]] + 1; + queue.add(new int[] {cur[0]+1, cur[1]}); + } + } + } + + // 위로 올라갈 때: 맨 윗줄이 제한이 없어야 함 + if (cur[0] > 1 && visit[cur[0]-1][cur[1]] == 0) { + up: + for (int i = 0; i < w; i++) { + if (arr[cur[0] - 1][cur[1] + i] == 1) { + break up; + } + + if (i == w-1) { + visit[cur[0]-1][cur[1]] = visit[cur[0]][cur[1]] + 1; + queue.add(new int[] {cur[0]-1, cur[1]}); + } + } + } + + // 왼쪽: 맨 왼쪽이 제한이 없어야 함 + if (cur[1] > 1 && visit[cur[0]][cur[1]-1] == 0) { + left: + for (int i = 0; i < h; i++) { + if (arr[cur[0]+i][cur[1]-1] == 1) { + break left; + } + + if (i == h-1) { + visit[cur[0]][cur[1]-1] = visit[cur[0]][cur[1]] + 1; + queue.add(new int[] {cur[0], cur[1]-1}); + } + } + } + + // 오른쪽: 맨 오른쪽이 제한이 없어야 함 + if (cur[1]+w <= m && visit[cur[0]][cur[1]+1] == 0) { + right: + for (int i = 0; i < h; i++) { + if (arr[cur[0]+i][cur[1]+w] == 1) { + break right; + } + + if (i == h-1) { + visit[cur[0]][cur[1]+1] = visit[cur[0]][cur[1]] + 1; + queue.add(new int[] {cur[0], cur[1]+1}); + } + } + } + } + + return -1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + arr = new int[n+1][m+1]; + visit = new int[n+1][m+1]; + + for (int i = 1; i <= n; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 1; j <= m; j++) { + arr[i][j] = Integer.parseInt(st.nextToken()); + } + } + + st = new StringTokenizer(br.readLine()); + + h = Integer.parseInt(st.nextToken()); + w = Integer.parseInt(st.nextToken()); + sx = Integer.parseInt(st.nextToken()); + sy = Integer.parseInt(st.nextToken()); + fx = Integer.parseInt(st.nextToken()); + fy = Integer.parseInt(st.nextToken()); + } +} From 43dfc2726f35c78ee638ac695922b48cbc8c705b Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Sun, 22 Jan 2023 14:19:14 +0900 Subject: [PATCH 151/163] [BOJ-11437-JAVA] LCA --- java/BOJ/Gold/III/G3_11437.java | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 java/BOJ/Gold/III/G3_11437.java diff --git a/java/BOJ/Gold/III/G3_11437.java b/java/BOJ/Gold/III/G3_11437.java new file mode 100644 index 0000000..f5c2b3e --- /dev/null +++ b/java/BOJ/Gold/III/G3_11437.java @@ -0,0 +1,89 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/11437 + */ +package Gold.III; + +import java.io.*; +import java.util.*; + +public class G3_11437 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int[] parent; + static int n, m; + static StringBuffer sb = new StringBuffer(); + + public static void main(String[] args) throws IOException { + n = Integer.parseInt(br.readLine()); + parent = new int[n+1]; + parent[1] = 1; + ArrayList[] adj = new ArrayList[n+1]; + + for (int i = 0; i < n-1; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + if (adj[a] == null) { + adj[a] = new ArrayList<>(); + } + if (adj[b] == null) { + adj[b] = new ArrayList<>(); + } + adj[a].add(b); + adj[b].add(a); + } + + Queue queue = new LinkedList<>(); + queue.add(1); + + while (!queue.isEmpty()) { + int cur = queue.poll(); + + for (int child : adj[cur]) { + if (parent[child] == 0) { + parent[child] = cur; + queue.add(child); + } + } + } + + m = Integer.parseInt(br.readLine()); + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + findParent(a, b); + } + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void findParent(int a, int b) { + int ap = a; + Set set = new HashSet<>(); + while (ap > 1) { + set.add(ap); + ap = parent[ap]; + } + set.add(1); + + int bp = b; + while (bp > 1) { + if (set.contains(bp)) { + sb.append(bp + "\n"); + return; + } + bp = parent[bp]; + } + if (bp == 1) { + sb.append(1 + "\n"); + } + } +} From 2b913481f06b03e299844b36985cdc0c47a99100 Mon Sep 17 00:00:00 2001 From: dongjji Date: Fri, 27 Jan 2023 17:15:19 +0900 Subject: [PATCH 152/163] =?UTF-8?q?[BOJ-17396-JAVA]=20=EB=B0=B1=EB=8F=84?= =?UTF-8?q?=EC=96=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/V/G5_17396.java | 81 +++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 java/BOJ/Gold/V/G5_17396.java diff --git a/java/BOJ/Gold/V/G5_17396.java b/java/BOJ/Gold/V/G5_17396.java new file mode 100644 index 0000000..db88080 --- /dev/null +++ b/java/BOJ/Gold/V/G5_17396.java @@ -0,0 +1,81 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17396 + */ +package Gold.V; + +import java.io.*; +import java.util.*; + +public class G5_17396 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + static int[] sight; + static ArrayList[] list; + + static int n, m; + + public static void main(String[] args) throws IOException { + input(); + System.out.println(bfs()); + } + + public static long bfs() { + PriorityQueue queue = new PriorityQueue<>((a, b) -> Long.compare(a[1], b[1])); + long[] visit = new long[n]; + Arrays.fill(visit, 10000000001L); + visit[0] = 0; + queue.add(new long[] {0, 0}); + + while (!queue.isEmpty()) { + long[] cur = queue.poll(); + + if (cur[0] == n-1) { + return cur[1]; + } + + if (visit[(int) cur[0]] < cur[1]) { + continue; + } + + for (int[] next : list[(int) cur[0]]) { + if (visit[next[0]] > cur[1] + next[1]) { + visit[next[0]] = cur[1] + next[1]; + queue.add(new long[] {next[0], cur[1] + next[1]}); + } + } + } + + return -1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + sight = new int[n]; + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < n; i++) { + sight[i] = Integer.parseInt(st.nextToken()); + } + + list = new ArrayList[n]; + for (int i = 0; i < n; i++) { + list[i] = new ArrayList<>(); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int t = Integer.parseInt(st.nextToken()); + + if ((sight[a] == 0 && sight[b] == 0) || (a == n-1 && sight[b] == 0) || (b == n-1 && sight[a] == 0)) { + list[a].add(new int[] {b, t}); + list[b].add(new int[] {a, t}); + } + } + } +} From a6d35abe9d8b113f660cd3a171b147c8ac40e3ff Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 30 Jan 2023 15:59:58 +0900 Subject: [PATCH 153/163] =?UTF-8?q?[BOJ-13424-JAVA]=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=20=EB=AA=A8=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_13424.java | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_13424.java diff --git a/java/BOJ/Gold/IV/G4_13424.java b/java/BOJ/Gold/IV/G4_13424.java new file mode 100644 index 0000000..2d12b2d --- /dev/null +++ b/java/BOJ/Gold/IV/G4_13424.java @@ -0,0 +1,102 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/13424 + */ +package Gold.IV; + +import java.io.*; +import java.util.StringTokenizer; + +public class G4_13424 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n, m, k; + static int answer; + static int[][] adj; + static int[] friend; + + public static void main(String[] args) throws IOException { + int t = Integer.parseInt(br.readLine()); + StringBuffer sb = new StringBuffer(); + + for (int testcase = 0; testcase < t; testcase++) { + input(); + floyd(); + + int min = Integer.MAX_VALUE; + for (int i = 1; i <= n; i++) { + int sum = 0; + for (int f : friend) { + sum += adj[f][i]; + } + + if (min > sum) { + min = sum; + answer = i; + } else if (min == sum) { + answer = Math.min(answer, i); + } + } + + sb.append(answer + "\n"); + } + + bw.write(sb.toString()); + + br.close(); + bw.flush(); + bw.close(); + } + + public static void floyd() { + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (k == i || i == j) { + continue; + } + + if (adj[i][j] > adj[i][k] + adj[k][j]) { + adj[i][j] = adj[i][k] + adj[k][j]; + } + } + } + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + + adj = new int[n+1][n+1]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (i == j) { + adj[i][j] = 0; + } else { + adj[i][j] = 1_000_000; + } + } + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + adj[a][b] = Math.min(adj[a][b], c); + adj[b][a] = Math.min(adj[b][a], c); + } + + k = Integer.parseInt(br.readLine()); + friend = new int[k]; + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < k; i++) { + friend[i] = Integer.parseInt(st.nextToken()); + } + } +} From c7e9524a8957a4088a0145ad0dbfb126a1ecc847 Mon Sep 17 00:00:00 2001 From: DongJoon Cha Date: Tue, 31 Jan 2023 17:40:53 +0900 Subject: [PATCH 154/163] =?UTF-8?q?[BOJ-14466-JAVA]=20=EC=86=8C=EA=B0=80?= =?UTF-8?q?=20=EA=B8=B8=EC=9D=84=20=EA=B1=B4=EB=84=88=EA=B0=84=20=EC=9D=B4?= =?UTF-8?q?=EC=9C=A06?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_14466.java | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_14466.java diff --git a/java/BOJ/Gold/IV/G4_14466.java b/java/BOJ/Gold/IV/G4_14466.java new file mode 100644 index 0000000..7d9805a --- /dev/null +++ b/java/BOJ/Gold/IV/G4_14466.java @@ -0,0 +1,118 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/14466 + */ +package Gold.IV; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G4_14466 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n, k, r; + static ArrayList[][] farm; + static int[][] arr; + static ArrayList cows; + static boolean[][] visit; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + StringBuffer sb = new StringBuffer(); + + int sum = 0; + for (int[] cow : cows) { + sum += bfs(cow); + } + + System.out.println(sum / 2); + } + + public static int bfs(int[] cow) { + int count = 0; + Queue queue = new LinkedList<>(); + visit = new boolean[n+1][n+1]; + visit[cow[0]][cow[1]] = true; + queue.add(cow); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx <= 0 || ny <= 0 || nx > n || ny > n || visit[nx][ny]) { + continue; + } + + boolean needRoad = false; + for (int[] road : farm[cur[0]][cur[1]]) { + if (road[0] == nx && road[1] == ny) { + needRoad = true; + } + } + + if (needRoad) { + continue; + } + + if (arr[nx][ny] == 1) { + count++; + } + + visit[nx][ny] = true; + queue.add(new int[] {nx, ny}); + } + } + + return k - count - 1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + r = Integer.parseInt(st.nextToken()); + + arr = new int[n+1][n+1]; + farm = new ArrayList[n+1][n+1]; + visit = new boolean[n+1][n+1]; + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + farm[i][j] = new ArrayList<>(); + } + } + + for (int i = 0; i < r; i++) { + st = new StringTokenizer(br.readLine()); + int r1 = Integer.parseInt(st.nextToken()); + int c1 = Integer.parseInt(st.nextToken()); + int r2 = Integer.parseInt(st.nextToken()); + int c2 = Integer.parseInt(st.nextToken()); + + farm[r1][c1].add(new int[] {r2, c2}); + farm[r2][c2].add(new int[] {r1, c1}); + } + + cows = new ArrayList<>(); + for (int i = 0; i < k; i++) { + st = new StringTokenizer(br.readLine()); + int r = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + arr[r][c] = 1; + + cows.add(new int[] {r, c}); + } + } +} From 8e18fbc69241485256e7e3fd86de23becdc11e72 Mon Sep 17 00:00:00 2001 From: dongjji Date: Thu, 2 Feb 2023 17:04:39 +0900 Subject: [PATCH 155/163] =?UTF-8?q?[BOJ-17244-JAVA]=20=EC=95=84=EB=A7=9E?= =?UTF-8?q?=EB=8B=A4=EC=9A=B0=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/II/G2_17244.java | 88 ++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 java/BOJ/Gold/II/G2_17244.java diff --git a/java/BOJ/Gold/II/G2_17244.java b/java/BOJ/Gold/II/G2_17244.java new file mode 100644 index 0000000..626e03f --- /dev/null +++ b/java/BOJ/Gold/II/G2_17244.java @@ -0,0 +1,88 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/17244 + */ +package Gold.II; + +import java.io.*; +import java.util.LinkedList; +import java.util.Queue; +import java.util.StringTokenizer; + +public class G2_17244 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer st; + + static int n, m; + static int count; + static int[] start; + static int[] end; + + static char[][] arr; + static int[][] key; + static int[][][] visit; + + static int[] dx = {1, -1, 0, 0}; + static int[] dy = {0, 0, 1, -1}; + + public static void main(String[] args) throws IOException { + input(); + bfs(); + + int keyCount = count == 0 ? 0 : (2 << (count-1)) - 1; + System.out.println(visit[end[0]][end[1]][keyCount]); + } + + public static void bfs() { + Queue queue = new LinkedList<>(); + queue.add(new int[] {start[0], start[1], 0}); + visit[start[0]][start[1]][0] = 0; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + for (int i = 0; i < 4; i++) { + int nx = cur[0] + dx[i]; + int ny = cur[1] + dy[i]; + + if (nx < 0 || ny < 0 || nx >= n || ny >= m) { + continue; + } + + if (arr[nx][ny] == '#') { + continue; + } + + if (visit[nx][ny][cur[2] | key[nx][ny]] == 0) { + visit[nx][ny][cur[2] | key[nx][ny]] = visit[cur[0]][cur[1]][cur[2]] + 1; + queue.add(new int[] {nx, ny, cur[2] | key[nx][ny] }); + } + } + } + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + m = Integer.parseInt(st.nextToken()); + n = Integer.parseInt(st.nextToken()); + + arr = new char[n][m]; + key = new int[n][m]; + visit = new int[n][m][64]; + count = 0; + for (int i = 0; i < n; i++) { + char[] line = br.readLine().toCharArray(); + for (int j = 0; j < m; j++) { + if (line[j] == 'S') { + start = new int[] {i, j}; + } else if (line[j] == 'E') { + end = new int[] {i, j}; + } else if (line[j] == 'X') { + key[i][j] = (int) Math.pow(2, count++); + } + + arr[i][j] = line[j]; + } + } + } +} From 44b0e56c6f27192305248dc6f0e056f4679dfb28 Mon Sep 17 00:00:00 2001 From: dongjji Date: Mon, 20 Feb 2023 10:48:14 +0900 Subject: [PATCH 156/163] =?UTF-8?q?[BOJ-18223-JAVA]=20=EB=AF=BC=EC=A4=80?= =?UTF-8?q?=EC=9D=B4=EC=99=80=20=EB=A7=88=EC=82=B0=20=EA=B7=B8=EB=A6=AC?= =?UTF-8?q?=EA=B3=A0=20=EA=B1=B4=EC=9A=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/BOJ/Gold/IV/G4_18223.java | 87 ++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 java/BOJ/Gold/IV/G4_18223.java diff --git a/java/BOJ/Gold/IV/G4_18223.java b/java/BOJ/Gold/IV/G4_18223.java new file mode 100644 index 0000000..de39e4c --- /dev/null +++ b/java/BOJ/Gold/IV/G4_18223.java @@ -0,0 +1,87 @@ +/** + * ? 문제 출처: 백준 온라인 져지(BOJ) + * ? https://www.acmicpc.net/problem/18223 + * + * ? 시간: 396ms + * ? 메모리: 23784KB + */ +package Gold.IV; + +import java.io.*; +import java.util.*; + +public class G4_18223 { + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer st; + + static int n, m, p; + static ArrayList[] adj; + + public static void main(String[] args) throws IOException { + input(); + int sDistance = bfs(1, n); + int fDistance = bfs(1, p) + bfs(p, n); + + if (sDistance == fDistance) { + bw.write("SAVE HIM"); + } else { + bw.write("GOOD BYE"); + } + + br.close(); + bw.flush(); + bw.close(); + } + + public static int bfs(int start, int end) { + Queue queue = new PriorityQueue<>((a, b) -> a[1] - b[1]); + queue.add(new int[] {start, 1}); + int[] visit = new int[n+1]; + visit[start] = 1; + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == end) { + return cur[1] - 1; + } + + if (cur[1] > visit[cur[0]]) { + continue; + } + + for (int[] next: adj[cur[0]]) { + if (visit[next[0]] == 0 || visit[next[0]] > cur[1] + next[1]) { + visit[next[0]] = cur[1] + next[1]; + queue.add(new int[] {next[0], visit[next[0]]}); + } + } + } + + return -1; + } + + public static void input() throws IOException { + st = new StringTokenizer(br.readLine()); + n = Integer.parseInt(st.nextToken()); + m = Integer.parseInt(st.nextToken()); + p = Integer.parseInt(st.nextToken()); + + adj = new ArrayList[n+1]; + for (int i = 1; i <= n; i++) { + adj[i] = new ArrayList<>(); + } + + for (int i = 0; i < m; i++) { + st = new StringTokenizer(br.readLine()); + + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + + adj[a].add(new int[] {b, c}); + adj[b].add(new int[] {a, c}); + } + } +} From b2b73dae0038d80f901e1e0e24a2de4ef3ddf98d Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 5 Sep 2023 11:53:07 +0900 Subject: [PATCH 157/163] =?UTF-8?q?[Programmers-181187-JAVA]=20=EB=91=90?= =?UTF-8?q?=20=EC=9B=90=20=EC=82=AC=EC=9D=B4=EC=9D=98=20=EC=A0=95=EC=88=98?= =?UTF-8?q?=20=EC=8C=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...354\240\225\354\210\230 \354\214\215.java" | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 "java/Programmers/Level2/\353\221\220 \354\233\220 \354\202\254\354\235\264\354\235\230 \354\240\225\354\210\230 \354\214\215.java" diff --git "a/java/Programmers/Level2/\353\221\220 \354\233\220 \354\202\254\354\235\264\354\235\230 \354\240\225\354\210\230 \354\214\215.java" "b/java/Programmers/Level2/\353\221\220 \354\233\220 \354\202\254\354\235\264\354\235\230 \354\240\225\354\210\230 \354\214\215.java" new file mode 100644 index 0000000..975721f --- /dev/null +++ "b/java/Programmers/Level2/\353\221\220 \354\233\220 \354\202\254\354\235\264\354\235\230 \354\240\225\354\210\230 \354\214\215.java" @@ -0,0 +1,26 @@ +// https://school.programmers.co.kr/learn/courses/30/lessons/181187 + +class Solution { + public long solution(int r1, int r2) { + long answer = 0; + + for (int x = 1; x < r2; x++) { + double sy = Math.sqrt(Math.pow(r1, 2) - Math.pow(x, 2)); + double by = Math.sqrt(Math.pow(r2, 2) - Math.pow(x, 2)); + long count = (long) by - (long) sy; + if (x == r1) { + count -= 1; + } + + answer += 4L * count; + + if (sy % 1 == 0) { + answer += 4L; + } + } + + answer += 4 * (r2 - r1 + 1); + + return answer; + } +} \ No newline at end of file From 094e9d077a4a7503cabd5bacd6d14e418a10ad34 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 5 Sep 2023 12:34:12 +0900 Subject: [PATCH 158/163] =?UTF-8?q?[Programmers-178871-JAVA]=20=EB=8B=AC?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=EA=B2=BD=EC=A3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...352\270\260 \352\262\275\354\243\274.java" | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 "java/Programmers/Level1/\353\213\254\353\246\254\352\270\260 \352\262\275\354\243\274.java" diff --git "a/java/Programmers/Level1/\353\213\254\353\246\254\352\270\260 \352\262\275\354\243\274.java" "b/java/Programmers/Level1/\353\213\254\353\246\254\352\270\260 \352\262\275\354\243\274.java" new file mode 100644 index 0000000..d2df077 --- /dev/null +++ "b/java/Programmers/Level1/\353\213\254\353\246\254\352\270\260 \352\262\275\354\243\274.java" @@ -0,0 +1,32 @@ +// https://school.programmers.co.kr/learn/courses/30/lessons/178871 + +import java.util.*; + +class Solution { + public String[] solution(String[] players, String[] callings) { + HashMap hm = new HashMap<>(); + HashMap hm2 = new HashMap<>(); + String[] answer = new String[players.length]; + + for (int i = 0; i < players.length; i++) { + hm.put(players[i], i); + hm2.put(i, players[i]); + } + + for (String call : callings) { + // 바로 앞의 선수 이름 + String loser = hm2.get(hm.get(call)-1); + + hm.put(call, hm.get(call) - 1); + hm.put(loser, hm.get(loser) + 1); + hm2.put(hm.get(call), call); + hm2.put(hm.get(loser), loser); + } + + hm.forEach((key, value) -> { + answer[value] = key; + }); + + return answer; + } +} \ No newline at end of file From 275ee7ad02dc15a294e70981444cfddbb3e90268 Mon Sep 17 00:00:00 2001 From: dongjji Date: Tue, 5 Sep 2023 12:34:38 +0900 Subject: [PATCH 159/163] =?UTF-8?q?[Programmers-178870-JAVA]=20=EC=97=B0?= =?UTF-8?q?=EC=86=8D=EB=90=9C=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=97=B4?= =?UTF-8?q?=EC=9D=98=20=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...354\227\264\354\235\230 \355\225\251.java" | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 "java/Programmers/Level2/\354\227\260\354\206\215\353\220\234 \353\266\200\353\266\204 \354\210\230\354\227\264\354\235\230 \355\225\251.java" diff --git "a/java/Programmers/Level2/\354\227\260\354\206\215\353\220\234 \353\266\200\353\266\204 \354\210\230\354\227\264\354\235\230 \355\225\251.java" "b/java/Programmers/Level2/\354\227\260\354\206\215\353\220\234 \353\266\200\353\266\204 \354\210\230\354\227\264\354\235\230 \355\225\251.java" new file mode 100644 index 0000000..3c8f616 --- /dev/null +++ "b/java/Programmers/Level2/\354\227\260\354\206\215\353\220\234 \353\266\200\353\266\204 \354\210\230\354\227\264\354\235\230 \355\225\251.java" @@ -0,0 +1,36 @@ +// https://school.programmers.co.kr/learn/courses/30/lessons/178870 + +class Solution { + public int[] solution(int[] sequence, int k) { + int[] answer = {0, 0}; + int left = 0; + int right = 0; + int sum = 0; + int gap = Integer.MAX_VALUE; + + while (left <= right && right < sequence.length) { + sum += sequence[right]; + + if (sum == k && gap > (right - left)) { + gap = right - left; + answer[0] = left; + answer[1] = right; + } + + while (sum >= k) { + sum -= sequence[left]; + left++; + + if (sum == k && gap > (right - left)) { + gap = right - left; + answer[0] = left; + answer[1] = right; + } + } + + right++; + } + + return answer; + } +} \ No newline at end of file From 400ac237cb1142eddfb9582991a8764c51cc87e0 Mon Sep 17 00:00:00 2001 From: devycha Date: Tue, 5 Sep 2023 18:13:54 +0900 Subject: [PATCH 160/163] =?UTF-8?q?[Programmers-176962-JAVA]=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=20=EC=A7=84=ED=96=89=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\355\226\211\355\225\230\352\270\260.java" | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 "java/Programmers/Level2/\352\263\274\354\240\234 \354\247\204\355\226\211\355\225\230\352\270\260.java" diff --git "a/java/Programmers/Level2/\352\263\274\354\240\234 \354\247\204\355\226\211\355\225\230\352\270\260.java" "b/java/Programmers/Level2/\352\263\274\354\240\234 \354\247\204\355\226\211\355\225\230\352\270\260.java" new file mode 100644 index 0000000..5e6a048 --- /dev/null +++ "b/java/Programmers/Level2/\352\263\274\354\240\234 \354\247\204\355\226\211\355\225\230\352\270\260.java" @@ -0,0 +1,70 @@ +// https://school.programmers.co.kr/learn/courses/30/lessons/176962 + +import java.util.*; + +class Solution { + public String[] solution(String[][] plans) { + String[] answer = new String[plans.length]; + int p = 0; + + Arrays.sort(plans, (a, b) -> { + String[] aTime = a[1].split(":"); + String[] bTime = b[1].split(":"); + + if (aTime[0].equals(bTime[0])) { + return Integer.parseInt(aTime[1]) - Integer.parseInt(bTime[1]); + } + + return Integer.parseInt(aTime[0]) - Integer.parseInt(bTime[0]); + }); + + Stack stack = new Stack<>(); + + for (int i = 0; i < plans.length; i++) { + if (i == plans.length - 1) { + System.out.println(plans[i][0] + " finished"); + answer[p++] = plans[i][0]; + // Stack으로 넘어가기 + while (!stack.isEmpty()) { + answer[p++] = stack.pop()[0]; + } + } else { + int gap = timeGap(plans[i][1], plans[i+1][1]); + + if (gap >= Integer.parseInt(plans[i][2])) { + answer[p++] = plans[i][0]; + gap -= Integer.parseInt(plans[i][2]); + System.out.println(plans[i][0] + " finished" + ", gap : " + gap); + // 남은 시간동안 스택에 쌓아온 일 하기 + while (gap > 0 && !stack.isEmpty()) { + String[] task = stack.pop(); + int leftTime = Integer.parseInt(task[1]); + if (leftTime > gap) { + leftTime -= gap; + gap = 0; + stack.push(new String[] {task[0], Integer.toString(leftTime)}); + } else { + System.out.println(task[0] + " finished" + ", gap : " + gap); + answer[p++] = task[0]; + gap -= leftTime; + } + } + } else { + int left = Integer.parseInt(plans[i][2]) - gap; + stack.push(new String[] {plans[i][0], Integer.toString(left)}); + } + } + } + + return answer; + } + + public int timeGap(String a, String b) { + int aHour = Integer.parseInt(a.split(":")[0]); + int bHour = Integer.parseInt(b.split(":")[0]); + int aMinute = Integer.parseInt(a.split(":")[1]); + int bMinute = Integer.parseInt(b.split(":")[1]); + return 60 * bHour + bMinute - 60*aHour - aMinute; + + } +} \ No newline at end of file From cb923cf9226d36ebd3d5e1e22431548e3a81ce01 Mon Sep 17 00:00:00 2001 From: devycha Date: Tue, 5 Sep 2023 19:15:39 +0900 Subject: [PATCH 161/163] =?UTF-8?q?[Programmers-172927-JAVA]=20=EA=B4=91?= =?UTF-8?q?=EB=AC=BC=20=EC=BA=90=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...353\254\274 \354\272\220\352\270\260.java" | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 "java/Programmers/Level2/\352\264\221\353\254\274 \354\272\220\352\270\260.java" diff --git "a/java/Programmers/Level2/\352\264\221\353\254\274 \354\272\220\352\270\260.java" "b/java/Programmers/Level2/\352\264\221\353\254\274 \354\272\220\352\270\260.java" new file mode 100644 index 0000000..c3f0b15 --- /dev/null +++ "b/java/Programmers/Level2/\352\264\221\353\254\274 \354\272\220\352\270\260.java" @@ -0,0 +1,70 @@ +// https://school.programmers.co.kr/learn/courses/30/lessons/172927 + +import java.util.*; + +class Solution { + public int solution(int[] picks, String[] minerals) { + int dia = picks[0]; + int iron = picks[1]; + int stone = picks[2]; + int Minpiro = Integer.MAX_VALUE; + + HashMap hm = new HashMap<>(); + hm.put("diamond", new int[] {1, 5, 25}); + hm.put("iron", new int[] {1, 1, 5}); + hm.put("stone", new int[] {1, 1, 1}); + + // 현재 곡괭이, 남은 횟수, 현재 피로도, 광물 순서, dia, iron, stone + // 0: dia + // 1: iron + // 2: stone + PriorityQueue pq = new PriorityQueue<>((a, b) -> { + return a[2] - b[2]; + }); + + if (dia > 0) { + pq.add(new int[] {0, 5, 0, 0, dia-1, iron, stone}); + } + + if (iron > 0) { + pq.add(new int[] {1, 5, 0, 0, dia, iron-1, stone}); + } + + if (stone > 0) { + pq.add(new int[] {2, 5, 0, 0, dia, iron, stone-1}); + } + + while (!pq.isEmpty()) { + int[] cur = pq.poll(); + if (cur[3] == minerals.length) { + return cur[2]; + } + + int piro = hm.get(minerals[cur[3]])[cur[0]]; // 현재 곡괭이로 현재 위치한 광물을 캘 때 피로도 + cur[1]--; // 곡괭이 남은 횟수 감소 + + if (cur[1] == 0) { + if (cur[4] == 0 && cur[5] == 0 && cur[6] == 0) { + Minpiro = Math.min(Minpiro, cur[2] + piro); + } else { + if (cur[4] > 0) { + pq.add(new int[] {0, 5, cur[2] + piro, cur[3]+1, cur[4]-1, cur[5], cur[6]}); + } + + if (cur[5] > 0) { + pq.add(new int[] {1, 5, cur[2] + piro, cur[3]+1, cur[4], cur[5]-1, cur[6]}); + } + + if (cur[6] > 0) { + pq.add(new int[] {2, 5, cur[2] + piro, cur[3]+1, cur[4], cur[5], cur[6]-1}); + } + } + + } else { + pq.add(new int[] {cur[0], cur[1], cur[2] + piro, cur[3]+1, cur[4], cur[5], cur[6]}); + } + } + + return Minpiro; + } +} \ No newline at end of file From 8d7f061ed5256f36947996685c611cac4a6351c6 Mon Sep 17 00:00:00 2001 From: devycha Date: Tue, 5 Sep 2023 20:13:26 +0900 Subject: [PATCH 162/163] =?UTF-8?q?[Programmers-169199-JAVA]=20=EB=A6=AC?= =?UTF-8?q?=EC=BD=94=EC=B3=87=20=EB=A1=9C=EB=B4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...354\263\207 \353\241\234\353\264\207.java" | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 "java/Programmers/Level2/\353\246\254\354\275\224\354\263\207 \353\241\234\353\264\207.java" diff --git "a/java/Programmers/Level2/\353\246\254\354\275\224\354\263\207 \353\241\234\353\264\207.java" "b/java/Programmers/Level2/\353\246\254\354\275\224\354\263\207 \353\241\234\353\264\207.java" new file mode 100644 index 0000000..ead1c6a --- /dev/null +++ "b/java/Programmers/Level2/\353\246\254\354\275\224\354\263\207 \353\241\234\353\264\207.java" @@ -0,0 +1,70 @@ +// https://school.programmers.co.kr/learn/courses/30/lessons/169199 + +import java.util.*; + +class Solution { + public int solution(String[] board) { + int[] dx = {1, -1, 0, 0}; + int[] dy = {0, 0, 1, -1}; + + int[] robot = new int[2]; + int[] goal = new int[2]; + int[][] road = new int[board.length][board[0].length()]; + + for (int i = 0; i < board.length; i++) { + char[] line = board[i].toCharArray(); + for (int j = 0; j < line.length; j++) { + if (line[j] == 'R') { + robot[0] = i; + robot[1] = j; + } else if (line[j] == 'G') { + goal[0] = i; + goal[1] = j; + } else if (line[j] == 'D') { + road[i][j] = 1; + } + } + } + + Queue queue = new LinkedList<>(); + int[][] visit = new int[road.length][road[0].length]; + visit[robot[0]][robot[1]] = 1; + queue.add(new int[] {robot[0], robot[1]}); + + while (!queue.isEmpty()) { + int[] cur = queue.poll(); + + if (cur[0] == goal[0] && cur[1] == goal[1]) { + return visit[cur[0]][cur[1]] - 1; + } + for (int k = 0; k < 4; k++) { + int nx = cur[0]; + int ny = cur[1]; + + while (true) { + if (nx + dx[k] < 0 || nx + dx[k] >= road.length) { + break; + } + + if (ny + dy[k] < 0 || ny + dy[k] >= road[0].length) { + break; + } + + if (road[nx + dx[k]][ny + dy[k]] == 1) { + break; + } + + nx += dx[k]; + ny += dy[k]; + } + + if (visit[nx][ny] == 0) { + visit[nx][ny] = visit[cur[0]][cur[1]] + 1; + queue.add(new int[] {nx, ny}); + } + } + } + + return -1; + } +} \ No newline at end of file From f9a0d27fb3448869acc3b53328688a2dd7e6b6b9 Mon Sep 17 00:00:00 2001 From: dongjji Date: Wed, 6 Sep 2023 12:57:58 +0900 Subject: [PATCH 163/163] =?UTF-8?q?[Programmers-172928-JAVA]=20=EA=B3=B5?= =?UTF-8?q?=EC=9B=90=20=EC=82=B0=EC=B1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...354\233\220 \354\202\260\354\261\205.java" | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 "java/Programmers/Level1/\352\263\265\354\233\220 \354\202\260\354\261\205.java" diff --git "a/java/Programmers/Level1/\352\263\265\354\233\220 \354\202\260\354\261\205.java" "b/java/Programmers/Level1/\352\263\265\354\233\220 \354\202\260\354\261\205.java" new file mode 100644 index 0000000..28271ea --- /dev/null +++ "b/java/Programmers/Level1/\352\263\265\354\233\220 \354\202\260\354\261\205.java" @@ -0,0 +1,50 @@ +// https://school.programmers.co.kr/learn/courses/30/lessons/172928 + +import java.util.*; + +class Solution { + public int[] solution(String[] park, String[] routes) { + int[] start = new int[] {0, 0}; + + HashMap hm = new HashMap<>(); + hm.put("N", new int[] {-1, 0}); + hm.put("S", new int[] {1, 0}); + hm.put("W", new int[] {0, -1}); + hm.put("E", new int[] {0, 1}); + + char[][] board = new char[park.length][park[0].length()]; + for (int i = 0; i < park.length; i++) { + char[] line = park[i].toCharArray(); + for (int j = 0; j < line.length; j++) { + board[i][j] = line[j]; + if (board[i][j] == 'S') { + start[0] = i; + start[1] = j; + } + } + } + + for (String route : routes) { + String way = route.split(" ")[0]; + int weight = Integer.parseInt(route.split(" ")[1]); + int nx = start[0]; + int ny = start[1]; + + for (int i = 0; i < weight; i++) { + nx += hm.get(way)[0]; + ny += hm.get(way)[1]; + + if (nx < 0 || ny < 0 || nx >= board.length || ny >= board[0].length || board[nx][ny] == 'X') { + break; + } + + if (i == weight-1) { + start[0] = nx; + start[1] = ny; + } + } + } + + return start; + } +} \ No newline at end of file