From fb1f1457116ae062328a1000ce79db1204aac20d Mon Sep 17 00:00:00 2001 From: dhdid Date: Mon, 6 Oct 2025 20:58:26 +0900 Subject: [PATCH] =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jugwang/week7/BOJ11724.java | 137 ++++++++++++++++++++++++ jugwang/week7/BOJ15591.java | 178 +++++++++++++++++++++++++++++++ jugwang/week7/BOJ1743.java | 169 +++++++++++++++++++++++++++++ jugwang/week7/BOJ18352.java | 184 ++++++++++++++++++++++++++++++++ jugwang/week7/BOJ2583.java | 207 ++++++++++++++++++++++++++++++++++++ 5 files changed, 875 insertions(+) create mode 100644 jugwang/week7/BOJ11724.java create mode 100644 jugwang/week7/BOJ15591.java create mode 100644 jugwang/week7/BOJ1743.java create mode 100644 jugwang/week7/BOJ18352.java create mode 100644 jugwang/week7/BOJ2583.java diff --git a/jugwang/week7/BOJ11724.java b/jugwang/week7/BOJ11724.java new file mode 100644 index 0000000..d0555a2 --- /dev/null +++ b/jugwang/week7/BOJ11724.java @@ -0,0 +1,137 @@ +/* +연결 요소의 개수 (백준 11724번) + +- 시간 복잡도: O(V + E) + - V: 정점의 개수, E: 간선의 개수 + - 모든 정점을 한 번씩 방문하고, 각 정점에서 인접한 정점들을 탐색 + - BFS를 통해 연결된 모든 정점을 방문하므로 O(V + E) + - 전체적으로 모든 정점과 간선을 한 번씩만 처리 + +- 풀이 + 1. 무방향 그래프에서 연결 요소(Connected Component)의 개수를 구하는 문제 + 2. 연결 요소란 서로 연결된 정점들의 집합으로, 다른 연결 요소와는 경로가 없음 + 3. BFS 또는 DFS를 사용하여 각 연결 요소를 탐색 + 4. 방문하지 않은 정점에서 BFS를 시작할 때마다 하나의 연결 요소를 발견 + 5. 모든 정점을 확인하여 총 연결 요소의 개수를 계산 + +- 의사코드 + ``` + solution(graph, nodeCount): + count = 0 + + for i = 1 to nodeCount: + if not visited[i]: + BFS(i, graph) // 새로운 연결 요소 발견 + count++ + + return count + + BFS(startNode, graph): + queue = new Queue() + queue.add(startNode) + visited[startNode] = true + + while queue is not empty: + currentNode = queue.poll() + + for each neighbor in graph[currentNode]: + if not visited[neighbor]: + visited[neighbor] = true + queue.add(neighbor) + ``` + +*/ + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Queue; + +class Solution { + boolean[] visited; + + public Solution(int node) { + this.visited = new boolean[node+1]; + } + + public int solution(ArrayList> graph, int node) { + int count = 0; + + for(int i=1; i<=node; i++) { + if(!visited[i]) { + visited[i] = true; + bfs(i, graph); + count++; + } + } + return count; + } + + public void bfs(int startNode, ArrayList> graph) { + Queue q = new ArrayDeque<>(); + + q.add(startNode); + visited[startNode] = true; + + while(!q.isEmpty()){ + int currentNode = q.poll(); + + visited[currentNode] = true; + + for (int neighbor : graph.get(currentNode)) { + if (!visited[neighbor]) { + visited[neighbor] = true; + q.add(neighbor); + } + } + } + } +} + +public class BOJ11724 { + public static void main(String[] args) { + // Test cases + int[] vertices = {6, 6}; + int[] edgeCounts = {5, 8}; + int[][][] edges = { + {{1, 2}, {2, 5}, {5, 1}, {3, 4}, {4, 6}}, + {{1, 2}, {2, 5}, {5, 1}, {3, 4}, {4, 6}, {5, 4}, {2, 4}, {2, 3}} + }; + int[] expectedResults = {2, 1}; + + for (int t = 0; t < vertices.length; t++) { + System.out.println("--- Test Case " + (t + 1) + " ---"); + + int vertex = vertices[t]; + int edgeCount = edgeCounts[t]; + + System.out.println("Vertices: " + vertex + ", Edges: " + edgeCount); + System.out.println("Edge connections:"); + for (int[] edge : edges[t]) { + System.out.println(" " + edge[0] + " - " + edge[1]); + } + + ArrayList> graph = new ArrayList<>(); + for (int i = 0; i <= vertex; i++) { + graph.add(new ArrayList<>()); + } + + // 간선 정보 설정 (무방향 그래프) + for (int[] edge : edges[t]) { + int node1 = edge[0]; + int node2 = edge[1]; + graph.get(node1).add(node2); + graph.get(node2).add(node1); + } + + Solution solved = new Solution(vertex); + int result = solved.solution(graph, vertex); + + System.out.println("Result: " + result + " connected components"); + System.out.println("Expected: " + expectedResults[t] + " connected components"); + + boolean isSuccess = (result == expectedResults[t]); + System.out.println(isSuccess ? ">>> SUCCESS" : ">>> FAILURE"); + System.out.println(); + } + } +} \ No newline at end of file diff --git a/jugwang/week7/BOJ15591.java b/jugwang/week7/BOJ15591.java new file mode 100644 index 0000000..21e299c --- /dev/null +++ b/jugwang/week7/BOJ15591.java @@ -0,0 +1,178 @@ +/* +MooTube (Silver) (백준 15591번) + +- 시간 복잡도: O(Q × N) + - Q: 쿼리 개수, N: 노드 개수 + - 각 쿼리마다 BFS로 트리 전체 탐색하므로 O(N) + - 전체 시간 복잡도는 O(Q × N) + +- 풀이 + 1. 트리에서 두 동영상 간의 경로상 가장 작은 가중치가 USADO 값 + 2. 시작 노드에서 BFS로 모든 연결된 노드 탐색 + 3. 경로상 최소 가중치가 k 이상인 노드들의 개수 계산 + 4. 각 쿼리마다 독립적으로 BFS 수행하여 조건을 만족하는 노드 개수 반환 + +- 슈도코드 + ``` + solution(questionNum, questions, nodeNum): + for each question: + distance = question[0] // 최소 USADO 값 + start = question[1] // 시작 노드 + result = BFS(distance, start, nodeNum) + return results + + BFS(distance, start, nodeNum): + count = 0 + visited[nodeNum+1] = false로 초기화 + queue = new Queue() + + queue.add([start, MAX_VALUE]) + visited[start] = true + + while queue is not empty: + current = queue.poll() + currentNode = current[0] + currentDistance = current[1] + + for each neighbor in adjacentList[currentNode]: + if not visited[neighbor.to]: + visited[neighbor.to] = true + newDistance = min(currentDistance, neighbor.weight) + if newDistance >= distance: + queue.add([neighbor.to, newDistance]) + count++ + + return count + ``` + +*/ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; + +class Node { + int to; + int weight; + + public Node(int to, int weight) { + this.to = to; + this.weight = weight; + } +} + +class Solution { + ArrayList> link; + + public Solution(int nodeNum) { + this.link = new ArrayList<>(); + for(int i=0; i<=nodeNum; i++) { + link.add(new ArrayList<>()); + } + } + + public int[] solution(int questionNum, int[][] questions, int nodeNum) { + int[] response = new int[questionNum]; + + for (int i=0; i q = new LinkedList<>(); + + q.add(new int[]{start,Integer.MAX_VALUE}); + visited[start] = true; + + while (!q.isEmpty()) { + int[] poll = q.poll(); + + int currentNode = poll[0]; + int currentDistance = poll[1]; + + for (Node nextNode : link.get(currentNode)) { + if(!visited[nextNode.to]) { + visited[nextNode.to] = true; + int newDistance = Math.min(currentDistance, nextNode.weight); + if (newDistance >= distance) { + q.add(new int[]{nextNode.to, newDistance}); + count++; + } + } + } + } + + return count; + } +} + + +public class BOJ15591 { + public static void main(String[] args) { + // Test cases + int[] nodeNums = {4}; + int[] questionNums = {3}; + int[][][] edges = { + {{1, 2, 3}, {2, 3, 2}, {2, 4, 4}} + }; + int[][][] questions = { + {{1, 2}, {4, 1}, {3, 1}} + }; + int[][] expectedResults = { + {3, 0, 2} + }; + + for (int t = 0; t < nodeNums.length; t++) { + System.out.println("--- Test Case " + (t + 1) + " ---"); + + int nodeNum = nodeNums[t]; + int questionNum = questionNums[t]; + + System.out.println("Nodes: " + nodeNum + ", Questions: " + questionNum); + System.out.println("Edges:"); + for (int[] edge : edges[t]) { + System.out.println(" " + edge[0] + " - " + edge[1] + " (weight: " + edge[2] + ")"); + } + System.out.println("Questions:"); + for (int[] question : questions[t]) { + System.out.println(" k=" + question[0] + ", start=" + question[1]); + } + + Solution solved = new Solution(nodeNum); + + // 간선 추가 + for (int[] edge : edges[t]) { + solved.link.get(edge[0]).add(new Node(edge[1], edge[2])); + solved.link.get(edge[1]).add(new Node(edge[0], edge[2])); + } + + int[] results = solved.solution(questionNum, questions[t], nodeNum); + + System.out.print("Results: "); + for (int i = 0; i < results.length; i++) { + System.out.print(results[i]); + if (i < results.length - 1) System.out.print(", "); + } + System.out.println(); + + System.out.print("Expected: "); + for (int i = 0; i < expectedResults[t].length; i++) { + System.out.print(expectedResults[t][i]); + if (i < expectedResults[t].length - 1) System.out.print(", "); + } + System.out.println(); + + boolean isSuccess = java.util.Arrays.equals(results, expectedResults[t]); + System.out.println(isSuccess ? ">>> SUCCESS" : ">>> FAILURE"); + System.out.println(); + } + } +} \ No newline at end of file diff --git a/jugwang/week7/BOJ1743.java b/jugwang/week7/BOJ1743.java new file mode 100644 index 0000000..91ad2d2 --- /dev/null +++ b/jugwang/week7/BOJ1743.java @@ -0,0 +1,169 @@ +/* +음식물 피하기 (백준 1743번) + +- 시간 복잡도: O(N × M + K) + - N: 세로 크기, M: 가로 크기, K: 음식물 쓰레기 개수 + - 모든 음식물 쓰레기 위치를 한 번씩 방문하고, BFS로 연결된 음식물 덩어리를 탐색 + - 각 음식물은 최대 한 번만 방문되므로 O(K) + - 전체적으로 O(N × M + K) + +- 풀이 + 1. N×M 통로에서 떨어진 음식물 쓰레기들이 상하좌우로 인접하면 하나의 덩어리가 됨 + 2. 가장 큰 음식물 덩어리의 크기를 구하는 문제 + 3. BFS를 사용하여 각 음식물 쓰레기에서 시작해 연결된 덩어리의 크기를 계산 + 4. 방문하지 않은 음식물 쓰레기에서만 BFS를 시작 + 5. 모든 덩어리 중 가장 큰 크기를 반환 + +- 의사코드 + ``` + solution(passage, row, col, locations): + maxSize = 0 + + for each food in locations: + if not visited[food.y][food.x]: + clusterSize = BFS(food, row, col, passage) + maxSize = max(maxSize, clusterSize) + + return maxSize + + BFS(startNode, row, col, passage): + queue = new Queue() + directions = [(0,1), (0,-1), (-1,0), (1,0)] + count = 1 + + queue.add(startNode) + visited[startNode.y][startNode.x] = true + + while queue is not empty: + current = queue.poll() + cx = current.x, cy = current.y + + for each direction in directions: + nx = cx + dx, ny = cy + dy + + if 범위 내 and passage[ny][nx] and not visited[ny][nx]: + visited[ny][nx] = true + queue.add(new Node(nx, ny)) + count++ + + return count + ``` + +*/ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; + +class Node { + int x; + int y; + + public Node(int x, int y) { + this.x = x; + this.y = y; + } +} + +class Solution { + boolean[][] visited; + int[] dx = {0, 0, -1, 1}; + int[] dy = {1, -1, 0, 0}; + + public Solution(int row, int col) { + this.visited = new boolean[row+1][col+1]; + } + + public int solution(boolean[][] passage, int row, int col, ArrayList location) { + int max = 0; + + for (Node i : location) { + if(!visited[i.y][i.x]){ + int count = bfs(i, row, col, passage); + if(count>max) { + max = count; + } + } + } + return max; + } + + public int bfs(Node node, int row, int col, boolean[][] passage) { + int count = 1; + Queue q = new LinkedList(); + + q.add(node); + visited[node.y][node.x] = true; + + while (!q.isEmpty()) { + Node poll = q.poll(); + int cx = poll.x; + int cy = poll.y; + + for (int i=0; i<4; i++) { + int nx = cx + dx[i]; + int ny = cy + dy[i]; + + if((1<=nx&&nx<=col) && (1<=ny&&ny<=row)) { + if(passage[ny][nx]){ + if(!visited[ny][nx]) { + visited[ny][nx] = true; + q.add(new Node(nx, ny)); + count++; + } + } + } + } + } + + return count; + } +} + +public class BOJ1743 { + public static void main(String[] args) { + // Test cases + int[] rows = {3}; + int[] cols = {4}; + int[] foodWasteCounts = {5}; + int[][][] foodPositions = { + {{3, 2}, {2, 2}, {3, 1}, {2, 3}, {1, 1}} + }; + int[] expectedResults = {4}; + + for (int t = 0; t < rows.length; t++) { + System.out.println("--- Test Case " + (t + 1) + " ---"); + + int row = rows[t]; + int col = cols[t]; + int foodWaste = foodWasteCounts[t]; + + System.out.println("Grid: " + row + " x " + col + ", Food waste count: " + foodWaste); + System.out.println("Food positions:"); + for (int[] pos : foodPositions[t]) { + System.out.println(" (" + pos[0] + "," + pos[1] + ")"); + } + + boolean[][] passage = new boolean[row+1][col+1]; + ArrayList location = new ArrayList<>(); + + // 음식물 쓰레기 위치 설정 + for (int[] pos : foodPositions[t]) { + int y = pos[0]; + int x = pos[1]; + passage[y][x] = true; + location.add(new Node(x, y)); + } + + Solution solved = new Solution(row, col); + int result = solved.solution(passage, row, col, location); + + System.out.println("Result: " + result); + System.out.println("Expected: " + expectedResults[t]); + + boolean isSuccess = (result == expectedResults[t]); + System.out.println(isSuccess ? ">>> SUCCESS" : ">>> FAILURE"); + System.out.println(); + } + } +} \ No newline at end of file diff --git a/jugwang/week7/BOJ18352.java b/jugwang/week7/BOJ18352.java new file mode 100644 index 0000000..7ae712f --- /dev/null +++ b/jugwang/week7/BOJ18352.java @@ -0,0 +1,184 @@ +/* +특정 거리의 도시 찾기 (백준 18352번) + +- 시간 복잡도: O(V + E) + - V: 도시의 개수, E: 도로의 개수 + - BFS로 그래프를 한 번 탐색하므로 O(V + E) + - 결과 정렬 시 O(K log K) (K는 결과 도시 개수) + +- 풀이 + 1. 방향 그래프에서 시작 도시로부터 정확히 K 거리에 있는 모든 도시 찾기 + 2. BFS를 사용하여 레벨별로 탐색 (각 레벨이 거리를 의미) + 3. 거리 K에 도달한 모든 도시를 결과 리스트에 저장 + 4. 결과가 없으면 -1 출력, 있으면 오름차순 정렬하여 출력 + +- 슈도코드 + ``` + BFS(startNode, targetDistance): + queue = new Queue() + visited[V] = false로 초기화 + resultCities = new List() + + queue.add([startNode, 0]) + visited[startNode] = true + + while queue is not empty: + current = queue.poll() + currentNode = current[0] + currentDistance = current[1] + + if currentDistance == targetDistance: + resultCities.add(currentNode) + continue + + if currentDistance > targetDistance: + continue + + for each neighbor in adjacentList[currentNode]: + if not visited[neighbor]: + visited[neighbor] = true + queue.add([neighbor, currentDistance + 1]) + + if resultCities is empty: + return [-1] + else: + sort(resultCities) + return resultCities + ``` + +*/ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.Queue; + +class Node { + int x; + int y; + + public Node(int x, int y) { + this.x = x; + this.y = y; + } +} + +class Solution { + ArrayList> map = new ArrayList<>(); + ArrayList endNode = new ArrayList<>(); + boolean[] visited; + + public Solution(int nodeNum) { + for (int i=0; i()); + } + visited = new boolean[nodeNum]; + } + + public ArrayList solution(int startNode, int distance) { + bfs(startNode, distance); + if(endNode.isEmpty()) { + ArrayList result = new ArrayList<>(); + result.add(-1); + return result; + } + Collections.sort(endNode); + return endNode; + } + + public void bfs(int startNode, int distance) { + Queue q = new LinkedList<>(); + + q.add(new int[]{startNode, 0}); + visited[startNode] = true; + + while (!q.isEmpty()) { + int[] poll = q.poll(); + int node = poll[0]; + int count = poll[1]; + + if (count == distance) { + endNode.add(node); + continue; + } else if (count > distance) { + continue; + } + + for(int neighbor : map.get(node)) { + if(visited[neighbor]) continue; + visited[neighbor] = true; + q.add(new int[]{neighbor, count+1}); + } + } + } +} + +public class BOJ18352 { + public static void main(String[] args) { + // Test cases + int[] cityNums = {4, 4, 4}; + int[] roadNums = {4, 3, 4}; + int[] distances = {2, 2, 1}; + int[] startCities = {1, 1, 1}; + int[][][] roads = { + {{1, 2}, {1, 3}, {2, 3}, {2, 4}}, + {{1, 2}, {1, 3}, {1, 4}}, + {{1, 2}, {1, 3}, {2, 3}, {2, 4}} + }; + int[][] expectedResults = { + {4}, + {-1}, + {2, 3} + }; + + for (int t = 0; t < cityNums.length; t++) { + System.out.println("--- Test Case " + (t + 1) + " ---"); + + int cityNum = cityNums[t]; + int roadNum = roadNums[t]; + int distance = distances[t]; + int startCity = startCities[t]; + + System.out.println("Cities: " + cityNum + ", Roads: " + roadNum + ", Distance: " + distance + ", Start: " + startCity); + System.out.println("Roads:"); + for (int[] road : roads[t]) { + System.out.println(" " + road[0] + " -> " + road[1]); + } + + Solution solved = new Solution(cityNum + 1); + + // 도로 추가 + for (int[] road : roads[t]) { + solved.map.get(road[0]).add(road[1]); + } + + ArrayList results = solved.solution(startCity, distance); + + System.out.print("Results: "); + for (int i = 0; i < results.size(); i++) { + System.out.print(results.get(i)); + if (i < results.size() - 1) System.out.print(", "); + } + System.out.println(); + + System.out.print("Expected: "); + for (int i = 0; i < expectedResults[t].length; i++) { + System.out.print(expectedResults[t][i]); + if (i < expectedResults[t].length - 1) System.out.print(", "); + } + System.out.println(); + + boolean isSuccess = results.size() == expectedResults[t].length; + if (isSuccess) { + for (int i = 0; i < results.size(); i++) { + if (results.get(i) != expectedResults[t][i]) { + isSuccess = false; + break; + } + } + } + System.out.println(isSuccess ? ">>> SUCCESS" : ">>> FAILURE"); + System.out.println(); + } + } +} diff --git a/jugwang/week7/BOJ2583.java b/jugwang/week7/BOJ2583.java new file mode 100644 index 0000000..c03d510 --- /dev/null +++ b/jugwang/week7/BOJ2583.java @@ -0,0 +1,207 @@ +/* +영역 구하기 (백준 2583번) + +- 시간 복잡도: O(M × N) + - M: 세로 크기, N: 가로 크기 + - 모든 셀을 한 번씩 방문하고, BFS로 연결된 영역을 탐색 + - 각 셀은 최대 한 번만 방문되므로 O(M × N) + - 결과 정렬 시 O(K log K) (K는 영역의 개수) + +- 풀이 + 1. M×N 격자에서 직사각형들로 막힌 영역을 제외한 빈 공간의 영역들을 찾는 문제 + 2. 직사각형 좌표를 이용해 격자에 막힌 부분을 표시 (true로 설정) + 3. BFS를 사용하여 연결된 빈 공간(false) 영역들을 탐색 + 4. 각 영역의 크기를 계산하고 오름차순으로 정렬하여 출력 + 5. 영역의 개수와 각 영역의 크기를 반환 + +- 슈도코드 + ``` + solution(row, col): + count = 0 + areas = new List() + + for i = 0 to col-1: + for j = 0 to row-1: + if not visited[j][i] and not grid[j][i]: // 빈 공간이면 + visited[j][i] = true + areaSize = BFS(i, j) + areas.add(areaSize) + count++ + + sort(areas) + return count, areas + + BFS(startX, startY): + queue = new Queue() + directions = [(0,1), (0,-1), (-1,0), (1,0)] + count = 1 + + queue.add([startX, startY]) + + while queue is not empty: + current = queue.poll() + cx = current[0], cy = current[1] + + for each direction in directions: + nx = cx + dx, ny = cy + dy + + if 범위 내 and not visited[ny][nx] and not grid[ny][nx]: + visited[ny][nx] = true + queue.add([nx, ny]) + count++ + + return count + ``` + +*/ + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.Queue; + +class Node { + int x; + int y; + + public Node(int x, int y) { + this.x = x; + this.y = y; + } +} + +class Solution { + boolean[][] visited; + boolean[][] grid; + ArrayList extent = new ArrayList<>(); + + int[] dx = {0, 0, -1, 1}; + int[] dy = {1, -1, 0, 0}; + + public Solution(int row, int col) { + this.visited = new boolean[row][col]; + this.grid = new boolean[row][col]; + } + + public int[] solution(int row, int col) { + int num = 0; + + for(int i=0; i q = new LinkedList(); + + q.add(node); + + while(!q.isEmpty()) { + Node poll = q.poll(); + + int cx = poll.x; + int cy = poll.y; + + for (int i=0; i<4; i++) { + int nx = cx + dx[i]; + int ny = cy + dy[i]; + + if((0<=nx&&nx>> SUCCESS" : ">>> FAILURE"); + System.out.println(); + } + } + + public static void drawing(int x1, int y1, int x2, int y2, boolean[][] grid) { + for (int y=y1; y