-
20303 - 할로윈의 양아치 JAVABaekjoon 2024. 2. 27. 14:57
1차원 냅색 + 그래프 개념이 포함된 문제이다.
첫번째 아이디어 : 한 명이 사탕을 뺏기면 친구들도 다 뺏긴다 -> BFS 탐색으로 친구들끼리 묶을 수 있다.
친구들끼리 묶어 하나의 입력으로 만든다. 그 후, 배낭 문제처럼 풀이한다.
예시를 들어보자.
각 사람마다 사탕의 개수를 갖고 있는 배열을 candies[]라고 하자.
N번째 사람을 생각해봤을 때, 해당 사람과 연결된 친구가 없을 경우 무게가 1이고 사탕의 개수가 candies[N]인 배낭 하나로 생각할 수 있다. (이 부분을 생각하지 못해서 틀렸었다.. 친구 관계가 없는 사람도 있음)
N번째 사람이 연결된 친구가 있을 경우, (자신 + 친구들의 수)만큼의 무게이고 사탕의 개수가 (candies[N] + candies[친구들의 idx])인 배낭 하나로 만들 수 있다.
++ 추가적으로 사람의 수와 친구들의 수가 꽤 많기 때문에, 2차원 배낭 문제로 해결하게되면 메모리를 많이 쓰게 된다. 따라서 K - 1부터 탐색해 배낭 문제를 풀이하는 방식을 채택하면, 메모리 사용량을 많이 줄일 수 있다.
배낭으로 사용할 클래스
static class Bag { int weight; int candy; Bag(int weight, int candy) { this.weight = weight; this.candy = candy; } @Override public String toString() { return weight + " " + candy; } }
각 친구들과의 관계를 이용해 모두 배낭으로 만듦
-> adjList에는 N + 1만큼의 ArrayList를 가지고 있다.(1번부터 시작하기 위함)
public static ArrayList<Bag> findBags(int[] candies, ArrayList<ArrayList<Integer>> adjList) { // 가방 찾기 ArrayList<Bag> retArr = new ArrayList<>(); boolean[] visited = new boolean[candies.length]; // 이미 가방으로 만든 친구들을 제외하기위한 visited 배열 for (int i = 1; i < adjList.size(); i++) { if (!visited[i]) { visited[i] = true; int candy = candies[i]; int weight = 1; Queue<Integer> que = new ArrayDeque<>(); que.offer(i); while (!que.isEmpty()) { int target = que.poll(); for (int elem : adjList.get(target)) { if (!visited[elem]) { que.offer(elem); visited[elem] = true; weight++; candy += candies[elem]; } } } retArr.add(new Bag(weight, candy)); } } for (int i = 1; i < visited.length; i++) { // 친구가 없는 사람들은 무게가 1인 배낭으로 꼭 변환해주어야 한다. if (!visited[i]) { visited[i] = true; retArr.add(new Bag(1, candies[i])); } } return retArr; }
입력 받기 + 배낭으로 만든 후 배낭 문제 풀이 형식으로 답안 출력
public static void main(String[] args) throws IOException { 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 K = Integer.parseInt(st.nextToken()); st = new StringTokenizer(br.readLine()); ArrayList<ArrayList<Integer>> adjList = new ArrayList<ArrayList<Integer>>(); int[] candies = new int[N + 1]; adjList.add(new ArrayList<>()); for (int i = 1; i <= N; i++) { // candies -> 해당 인간이 갖고 있는 사탕 수, adjList -> 친구 관계 candies[i] = Integer.parseInt(st.nextToken()); adjList.add(new ArrayList<>()); } for (int i = 0; i < M; i++) { st = new StringTokenizer(br.readLine()); int start = Integer.parseInt(st.nextToken()); int end = Integer.parseInt(st.nextToken()); adjList.get(start).add(end); adjList.get(end).add(start); } ArrayList<Bag> bags = findBags(candies, adjList); // K는 들 수 있는 가방 최대 무게 int[] dp = new int[K]; // K 무게를 만든다. N번째 가방을 써서 for (int bIdx = 0; bIdx < bags.size(); bIdx++) { Bag bag = bags.get(bIdx); for (int i = K - 1; i >= bag.weight; i--) { dp[i] = Math.max(dp[i], dp[i - bag.weight] + bag.candy); } } System.out.println(dp[K - 1]); }
'Baekjoon' 카테고리의 다른 글
백준(BOJ) 22342 - 계산로봇 (2) 2023.12.21 백준(BOJ) 25381 - ABBC (0) 2023.12.13 백준(BOJ) 25401 - 카드바꾸기 (1) 2023.12.07 1092 - 배 (0) 2023.09.07 14502 - 연구소 (2) 2022.12.28