diff --git "a/BOJ/1000-5000353円262円210円/DH_1967_2.java" "b/BOJ/1000-5000353円262円210円/DH_1967_2.java" new file mode 100644 index 00000000..ea0fa66f --- /dev/null +++ "b/BOJ/1000-5000353円262円210円/DH_1967_2.java" @@ -0,0 +1,64 @@ +import java.io.*; +import java.util.*; + +/* + * 트리의 지름 + */ + +public class DH_1967_2 { + static class Node { + int e, w; + public Node(int e, int w) { + this.e = e; + this.w = w; + } + } + static ArrayList adj[]; + static int maxIdx, maxDis; + + public static void main(String[] args) throws Exception { +// System.setIn(new FileInputStream("./input/BOJ1967.txt")); + + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + int n = Integer.parseInt(br.readLine()); + + adj = new ArrayList[n + 1]; + for(int i = 0; i < adj.length; i++) adj[i] = new ArrayList(); + + StringTokenizer st; + for(int i = 0; i < n - 1; i++) { + st = new StringTokenizer(br.readLine()); + int s = Integer.parseInt(st.nextToken()); + int e = Integer.parseInt(st.nextToken()); + int w = Integer.parseInt(st.nextToken()); + + adj[s].add(new Node(e, w)); + adj[e].add(new Node(s, w)); + } + + boolean[] v = new boolean[n + 1]; // 방문배열 + v[1] = true; // 임의의 시작점 + dfs(1, 0, v); // 임의의 시작점에서부터 dfs 시작 + + v = new boolean[n + 1]; // 방문배열 다시 초기화 + v[maxIdx] = true; // max: 처음 시작점(1)에서부터 가장 먼 지점 + dfs(maxIdx, 0, v); // 처음 시작점(1)에서부터 가장 먼 지점을 기준으로 가장 먼 지점 구하기 + + System.out.println(maxDis); + } + + static void dfs(int start, int dis, boolean[] v) { + if(dis> maxDis) { // dis: start노드까지 가기 위한 가중치 + maxIdx = start; + maxDis = dis; + } + + for(Node next: adj[start]) { + if(v[next.e]) continue; + + v[next.e] = true; + dfs(next.e, dis + next.w, v); + v[next.e] = false; + } + } +} diff --git "a/BOJ/1000-5000353円262円210円/DH_2110_2.java" "b/BOJ/1000-5000353円262円210円/DH_2110_2.java" new file mode 100644 index 00000000..bda19a16 --- /dev/null +++ "b/BOJ/1000-5000353円262円210円/DH_2110_2.java" @@ -0,0 +1,59 @@ +import java.io.*; +import java.util.*; + +/* + * 공유기 설치 + * 집의 좌표: x1, ..., xn + * 공유기 C개를 설치할 때, 인접한 거리를 가능한 크게 하여 설치하기 + * 집의 개수: N, 공유기 개수: C + */ + +public class DH_2110_2 { + public static void main(String[] args) throws Exception { + + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine()); + + int N = Integer.parseInt(st.nextToken()); // 집의 개수 + int C = Integer.parseInt(st.nextToken()); // 공유기의 개수 + + int[] arr = new int[N]; + + int s = 0, e = 0; + + for(int i = 0; i < N; i++) { + arr[i] = Integer.parseInt(br.readLine()); + e = Math.max(e, arr[i]); + } + + // 이분탐색을 위한 정렬 + Arrays.sort(arr); + + // 두 공유가 사이 거리의 최대값 → upper bound + while(s <= e) { + int m = (s + e) / 2; // 사이 간격이 tmp 일 때, 설치할 수 있는 공유기의 개수 구하기 + int cnt = getCnt(arr, m); + + // tmp일 때, 설치해야 되는 공유기 개수가 작다면 크기 줄이기 + if(cnt < C) e = m - 1; + else s = m + 1; + } + + System.out.println(e); + } + + // 공유기 사이 최대 거리가 tmp일 때, 설치해야 되는 공유기 개수 + // 왼쪽에 설치할 수록, 공유기를 최대한 많이 멀리 설치할 수 있음 → 첫 번째 집에 무조건 공유기 설치 + static int getCnt(int[] arr, int tmp) { + int cnt = 1, prev = arr[0]; + + for(int i = 1; i < arr.length; i++) { + if(arr[i] - prev>= tmp) { + cnt += 1; + prev = arr[i]; + } + } + + return cnt; + } +} diff --git "a/BOJ/1000-5000353円262円210円/DH_2805_2.java" "b/BOJ/1000-5000353円262円210円/DH_2805_2.java" new file mode 100644 index 00000000..18114a73 --- /dev/null +++ "b/BOJ/1000-5000353円262円210円/DH_2805_2.java" @@ -0,0 +1,58 @@ +import java.io.*; +import java.util.*; + +/* + * 나무 자르기 + */ + +public class DH_2805_2 { + public static void main(String[] args) throws Exception { + + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine()); + + int N = Integer.parseInt(st.nextToken()); + int M = Integer.parseInt(st.nextToken()); + + st = new StringTokenizer(br.readLine()); + + // s가 arr의 최솟값보다 작아질 수 있으므로 0으로 설정해주기 + long s = 0, e = Integer.MIN_VALUE; + + int[] arr = new int[N]; + + for(int i = 0; i < N; i++) { + arr[i] = Integer.parseInt(st.nextToken()); + e = Math.max(e, arr[i]); + } + + Arrays.sort(arr); + + // upper bound 구하기 + while(s <= e) { + long m = (s + e) / 2; + + long totalCutLength = getTotalCutLength(arr, m); + + // upper bound → 같을 때, 시작점 옮기기 + if(totalCutLength>= M) s = m + 1; + else e = m - 1; + } + + // upper bound 구하는 것이기 때문에 e 출력 + System.out.println(e); + } + + // m을 제한으로 했을 때, 잘리는 나무의 합계 + static long getTotalCutLength(int[] arr, long m) { + + long result = 0; + + for(long a: arr) { + if(a <= m) continue; + result += (a - m); + } + + return result; + } +} diff --git "a/BOJ/5001-10000353円262円210円/DH_5021_2.java" "b/BOJ/5001-10000353円262円210円/DH_5021_2.java" new file mode 100644 index 00000000..3cca1bae --- /dev/null +++ "b/BOJ/5001-10000353円262円210円/DH_5021_2.java" @@ -0,0 +1,110 @@ +import java.io.*; +import java.util.*; + +/* + * 왕위 계승 + */ + +public class DH_5021_2 { + + static HashMap nameToIdx = new HashMap(); + static int[] indegree; // 진입차수 배열 + static double[] power; // 혈통 점수 + static int idx; + + public static void main(String[] args) throws Exception { + System.setIn(new FileInputStream("./input/BOJ5021.txt")); + + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine()); + + int N = Integer.parseInt(st.nextToken()); // 가족 정보 + int M = Integer.parseInt(st.nextToken()); // 왕위 계승 주장 사람 정보 + + // 가족 정보가 N개이기 때문에, 사람은 최대 3N명까지 나올 수 있음! + indegree = new int[3 * N]; + power = new double[3 * N]; + + // 나라를 세운 사람 정보 + String s = br.readLine(); + nameToIdx.put(s, idx); + power[idx] = 1; + idx += 1; + + // 인접 리스트 저장 + ArrayList> adj = new ArrayList>(); + for(int i = 0; i < 3 * N; i++) adj.add(new ArrayList()); + + // 입력받는 가족 정보를 기반으로 인접 리스트 & 진입차수 배열 만들기 + for(int i = 0; i < N; i++) { + st = new StringTokenizer(br.readLine()); + + String s1 = st.nextToken(); // 자식 + String s2 = st.nextToken(); // 부모 1 + String s3 = st.nextToken(); // 부모 2 + + putName(s1); + putName(s2); + putName(s3); + + indegree[nameToIdx.get(s1)] += 2; + adj.get(nameToIdx.get(s2)).add(nameToIdx.get(s1)); + adj.get(nameToIdx.get(s3)).add(nameToIdx.get(s1)); + } + + // 위상정렬을 하기 위해 사용하는 큐 + ArrayDeque q = new ArrayDeque(); + + // 진입차수 배열이 0인 것들만 우선 큐에 넣어줌 + for(String key: nameToIdx.keySet()) { + int idx = nameToIdx.get(key); + + if(indegree[idx] != 0) continue; + q.add(idx); + + // 혈통점수가 0이면서 들어오는 간선이 없는 경우는 왕족이 아닌 사람이므로 + // 혈통점수를 0.5로 바꿔주기 + if(power[idx] == 0) power[idx] = 0.5; + } + + // 위상정렬 + while(!q.isEmpty()) { + int current = q.poll(); + + for(int next: adj.get(current)) { + // 진입차수 배열을 하나씩 없애기 + indegree[next]--; + + // 연결된 노드들의 혈통 점수 계산해주기 + power[next] += power[current] / 2; + + // 진입차수가 0이 된다면 큐에 넣어주기 + if(indegree[next] == 0) { + q.add(next); + } + } + } + + double maxPower = 0; + String result = null; + + // 왕위계승을 주장하는 사람들 중에서 혈통 점수가 가장 큰 사람 이름 출력하기 + for(int i = 0; i < M; i++) { + String name = br.readLine(); + + int key = nameToIdx.getOrDefault(name, -1); + + if(key == -1) continue; + if(maxPower < power[key]) { + maxPower = power[key]; + result = name; + } + } + + System.out.println(result); + } + + static void putName(String s) { + if(!nameToIdx.containsKey(s)) nameToIdx.put(s, idx++); + } +} diff --git "a/BOJ/5001-10000353円262円210円/DH_7579_2.java" "b/BOJ/5001-10000353円262円210円/DH_7579_2.java" new file mode 100644 index 00000000..41a51020 --- /dev/null +++ "b/BOJ/5001-10000353円262円210円/DH_7579_2.java" @@ -0,0 +1,53 @@ +import java.io.*; +import java.util.*; + +/* + * 앱 + */ + +public class DH_7579_2 { + public static void main(String[] args) throws Exception { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine()); + + int N = Integer.parseInt(st.nextToken()); + int M = Integer.parseInt(st.nextToken()); + + int[] weight = new int[N + 1]; + + st = new StringTokenizer(br.readLine()); + for(int i = 1; i < weight.length; i++) weight[i] = Integer.parseInt(st.nextToken()); + + int[] cost = new int[N + 1]; + st = new StringTokenizer(br.readLine()); + + int costSum = 0; + + for(int i = 1; i < cost.length; i++) { + cost[i] = Integer.parseInt(st.nextToken()); + costSum += cost[i]; + } + + // 1 ≤ M ≤ 10,000,000이기 때문에 바이트에 대해 2차원 배열을 만들면 메모리 초과가 발생함! + // knapsack[i][j]: i번째 바이트까지 확인했을 때, j비용을 사용한 경우 추가로 확보할 수 있는 메모리 크기 + int[][] knapsack = new int[N + 1][costSum + 1]; + + int result = 0; + + // M바이트를 확보하기 위한 앱 비활성화의 최소 비용 구하기 + for(int i = 1; i < weight.length; i++) { + for(int c = 0; c < knapsack[0].length; c++) { + if(cost[i] <= c) + knapsack[i][c] = Math.max(knapsack[i - 1][c - cost[i]] + weight[i], knapsack[i - 1][c]); + else knapsack[i][c] = knapsack[i - 1][c]; + + if(knapsack[i][c]>= M) { + result = c; + break; + } + } + } + + System.out.println(result); + } +} \ No newline at end of file diff --git "a/BOJ/5001-10000353円262円210円/DH_9084_2.java" "b/BOJ/5001-10000353円262円210円/DH_9084_2.java" new file mode 100644 index 00000000..ff20b9ea --- /dev/null +++ "b/BOJ/5001-10000353円262円210円/DH_9084_2.java" @@ -0,0 +1,40 @@ +import java.io.*; +import java.util.*; + +/* + * 동전 + */ + +public class DH_9084_2 { + public static void main(String[] args) throws Exception { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + StringBuilder sb = new StringBuilder(); + + int T = Integer.parseInt(br.readLine()); + + for(int tc = 0; tc < T; tc++) { + int N = Integer.parseInt(br.readLine()); // 동전의 가짓수 + + int[] arr = new int[N]; + + st = new StringTokenizer(br.readLine()); + for(int i = 0; i < arr.length; i++) arr[i] = Integer.parseInt(st.nextToken()); + + int M = Integer.parseInt(br.readLine()); + + int[] dp = new int[M + 1]; + + // dp[i]: i원을 만들 수 있는 가짓수 + dp[0] = 1; + + for(int i = 0; i < arr.length; i++) { + for(int j = arr[i]; j < dp.length; j++) { + dp[j] += dp[j - arr[i]]; + } + } + + System.out.println(dp[M]); + } + } +} diff --git "a/BOJ/5001-10000353円262円210円/DH_9205_2.java" "b/BOJ/5001-10000353円262円210円/DH_9205_2.java" new file mode 100644 index 00000000..9ac5ca20 --- /dev/null +++ "b/BOJ/5001-10000353円262円210円/DH_9205_2.java" @@ -0,0 +1,94 @@ +import java.io.*; +import java.util.*; + +/* + * 맥주 마시면서 걸어가기 + */ + +public class DH_9205_2 { + static class Point { + int x, y; + public Point(int x, int y) { + this.x = x; + this.y = y; + } + } + + static class Node { + int e, w; + public Node(int e, int w) { + this.e = e; + this.w = w; + } + } + public static void main(String[] args) throws Exception { +// System.setIn(new FileInputStream("./input/BOJ9205.txt")); + + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + + int t = Integer.parseInt(br.readLine()); // 테스트케이스 개수 + StringBuilder sb = new StringBuilder(); + + for(int tc = 0; tc < t; tc++) { + int n = Integer.parseInt(br.readLine()); // 맥주를 파는 편의점의 개수 + + // 집, 편의점, 락 페스티벌 좌표 입력받기 + Point[] points = new Point[n + 2]; + for(int i = 0; i < n + 2; i++) { + st = new StringTokenizer(br.readLine()); + + int x = Integer.parseInt(st.nextToken()); + int y = Integer.parseInt(st.nextToken()); + + points[i] = new Point(x, y); + } + + // 인접 리스트 만들어주기 + ArrayList> adj = new ArrayList>(); + for(int i = 0; i < n + 2; i++) adj.add(new ArrayList()); + + for(int i = 0; i < n + 2; i++) { + for(int j = 0; j < n + 2; j++) { + if(i == j) continue; + + int dis = Math.abs(points[i].x - points[j].x) + Math.abs(points[i].y - points[j].y); + + // 애초에 갈 수 없는 거리는 인접 리스트 생성할 때부터 제외 + if(dis> 20 * 50) continue; + + adj.get(i).add(new Node(j, dis)); + adj.get(j).add(new Node(i, dis)); + } + } + + if(bfs(adj)) sb.append("happy").append("\n"); + else sb.append("sad").append("\n"); + } + + System.out.println(sb); + } + + // bfs 탐색 + static boolean bfs(ArrayList> adj) { + boolean[] v = new boolean[adj.size()]; + + ArrayDeque q = new ArrayDeque(); + q.add(0); // 상근이네 집 + v[0] = true; + + while(!q.isEmpty()) { + int current = q.poll(); + + if(current == adj.size() - 1) return true; + + for(Node next: adj.get(current)) { + if(v[next.e]) continue; + q.add(next.e); + v[next.e] = true; + } + } + + return false; + } +} diff --git a/Programmers/Level3/DH_214288_2.java b/Programmers/Level3/DH_214288_2.java new file mode 100644 index 00000000..a90129ef --- /dev/null +++ b/Programmers/Level3/DH_214288_2.java @@ -0,0 +1,65 @@ +import java.util.*; + +/* + * 상담원 인원 + */ + +public class DH_214288_2 { + + static int result = Integer.MAX_VALUE; + + static int solution(int k, int n, int[][] reqs) { + + int[] question = new int[k]; // 각 상담마다 멘토가 몇 명이 배정이 되는지 저장 + func(0, n, k, question, n, reqs); + + return result; + } + + // 중복순열로 문제에 대해 멘토 인원 지정하기 + // value값을 통해 중복순열이면서, 각 상담에 배정된 인원의 합계가 n이 될 수 있도록 하기 + static void func(int depth, int n, int k, int[] question, int value, int[][] reqs) { + if(depth == k) { + if(value == 0) getWaitingTime(question, reqs); + return; + } + + for(int i = 1; i < n + 1; i++) { + question[depth] = i; + func(depth + 1, n, k, question, value - i, reqs); + } + } + + static void getWaitingTime(int[] question, int[][] reqs) { + + int waitingTime = 0; + + // 끝나는 순서를 오름차순으로 저장할 수 있도록 우선순위 큐 사용 + ArrayList> waitingQueue = new ArrayList>(); + for(int i = 0; i < question.length; i++) waitingQueue.add(new PriorityQueue()); + + for(int[] req: reqs) { + + int startAt = req[0]; // 시작 시간 + int spendTime = req[1]; // 상담에 걸리는 시간 + int type = req[2] - 1; // 상담 유형 번호 + + // 상담하고 있는 인원이 꽉 찬 경우 + // 제일 먼저 끝나는 상담이 현재 상담받을 사람의 시작 시간보다 늦게 끝난다면 대기하기 + // 그게 아니라면 대기 시간 없이 바로 상담 받기!→ + if(waitingQueue.get(type).size() == question[type]) { + int endAt = waitingQueue.get(type).poll(); + + if(endAt> startAt) { + waitingTime += (endAt - startAt); + startAt = endAt; + } + } + + // 현재 사람이 받는 상담 번호에 대해 언제 끝나는지 저장하기 + waitingQueue.get(type).add(startAt + spendTime); + } + + result = Math.min(result, waitingTime); + } +} diff --git a/Programmers/Level3/DH_42861_2.java b/Programmers/Level3/DH_42861_2.java new file mode 100644 index 00000000..14d499ae --- /dev/null +++ b/Programmers/Level3/DH_42861_2.java @@ -0,0 +1,49 @@ +import java.util.*; + +/* + * 섬 연결하기 + * 크루스칼을 통한 MST 구성 + */ + +public class DH_42861_2 { + static int[] p; + + public int solution(int n, int[][] costs) { + PriorityQueue pq = new PriorityQueue((o1, o2) -> Integer.compare(o1[2], o2[2])); + + // 간선들을 모두 우선순위 큐에 넣어주기 + for(int[] cost: costs) pq.add(cost); + + p = new int[n + 1]; + for(int i = 0; i < p.length; i++) p[i] = i; + + int result = 0, cnt = 0; + + // 노드가 n개 일 때, 간선은 n - 1개 + while(cnt != n - 1) { + int[] current = pq.poll(); + + if(find(current[0]) == find(current[1])) continue; + union(current[0], current[1]); + + result += current[2]; + cnt += 1; + } + + return result; + } + + // find → 경로 압축!!ᅣ + static int find(int a) { + return p[a] = a == p[a] ? a: find(p[a]); + } + + // union + static void union(int a, int b) { + a = find(a); + b = find(b); + + if(a != b) p[b] = a; + } + +} \ No newline at end of file diff --git "a/SQL/20354円243円274円354円260円250円/Immediate Food Delivery II.sql" "b/SQL/20354円243円274円354円260円250円/Immediate Food Delivery II.sql" new file mode 100644 index 00000000..d3d27886 --- /dev/null +++ "b/SQL/20354円243円274円354円260円250円/Immediate Food Delivery II.sql" @@ -0,0 +1,7 @@ +SELECT ROUND(SUM(CASE WHEN ORDER_DATE = CUSTOMER_PREF_DELIVERY_DATE THEN 1 ELSE 0 END) / COUNT(*) * 100, 2) `immediate_percentage` +FROM DELIVERY +WHERE (CUSTOMER_ID, ORDER_DATE) IN ( + SELECT CUSTOMER_ID, MIN(ORDER_DATE) + FROM DELIVERY + GROUP BY CUSTOMER_ID +) \ No newline at end of file

AltStyle によって変換されたページ (->オリジナル) /