반응형
문제 설명
- 한 아이의 사탕을 뺏으면 친구 것도 다 빼앗음
- K명 이상의 아이들이 울면 더 이상 뺏지 못함
=> K명 미만의 아이들 무리 부분집합 중 얻을 수 있는 최대 사탕 개수 출력하기
문제 풀이
이 문제는 0/1 Knapsack을 활용하는 문제이다.
0/1 Knapsack을 사용하기 위해서 인접리스트로 주어지는 아이들간의 관계를 이용한 아이들 무리를 만들어야 한다.
주어지는 인접리스트를 양방향으로 저장한 후 DFS를 이용하여 각각의 무리를 만들었다.
그 무리의 사람 수와 사탕 수를 저장하는 Group이라는 객체를 만들어 ArrayList에 저장했다.
그리고 Group을 전부 돌면서 1차원 배열로 dp(코드의 backpack)을 만들어 한계 사람 수(K) -1 부터 그 Group의 사람 수 까지 0/1Knapsack방식으로 수행하였고 최종적으로 배열의 가장 마지막인 K-1번째를 출력하여 답을 도출했다.
문제 풀이 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
public class _20303_할로윈의양아치 {
static class Group {
int people;
int candies;
Group(int people, int candies) {
this.people = people;
this.candies = candies;
}
}
static int N, M, K, candy[];
static int people, candies;
static ArrayList<Group> groups = new ArrayList<>();
static ArrayList<Integer> friends[];
static boolean visited[];
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(in.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
candy = new int[N];
friends = new ArrayList[N];
visited = new boolean[N];
st = new StringTokenizer(in.readLine());
for (int i = 0; i < N; ++i) {
candy[i] = Integer.parseInt(st.nextToken());
friends[i] = new ArrayList<>();
}
for (int i = 0; i < M; ++i) {
st = new StringTokenizer(in.readLine());
int a = Integer.parseInt(st.nextToken()) - 1;
int b = Integer.parseInt(st.nextToken()) - 1;
friends[a].add(b);
friends[b].add(a);
}
makeGroup(); // 그룹만들기
int[] backpack = new int[K]; //0/1Knapsack
for(int i = 0; i< groups.size();++i) {
Group g = groups.get(i);
for(int j = K-1; j>= g.people;--j) {
backpack[j] = Math.max(g.candies + backpack[j-g.people], backpack[j]);
}
}
System.out.println(backpack[K-1]);
}
static void makeGroup() { //그룹만들기
for (int i = 0; i < N; ++i) {
if (visited[i]) // 이미 그룹에 속한 아이라면
continue;
people = 1;
candies = candy[i];
visited[i] = true;
findFriends(i);
groups.add(new Group(people, candies));
}
}
static void findFriends(int idx) { //dfs
Iterator<Integer> iter = friends[idx].iterator();
while (iter.hasNext()) {
int num = iter.next();
if (visited[num])
continue;
++people;
candies += candy[num];
visited[num] = true;
findFriends(num);
}
}
}
반응형
'알고리즘 문제풀이 > 백준' 카테고리의 다른 글
Baekjoon_1541_잃어버린 괄호 (0) | 2020.12.15 |
---|---|
Baekjoon_2217_로프 (0) | 2020.12.15 |
Baekjoon_1074_Z (0) | 2020.12.14 |
Baekjoon_20208_진우의 민트초코우유 (0) | 2020.12.09 |
Baekjoon_2151_거울 설치 (0) | 2020.12.05 |