문제풀이/코딩테스트
백준 20303번 할로윈의 양아치 [Java]
gyungmean
2024. 7. 5. 16:23
문제
https://www.acmicpc.net/problem/20303
코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class Main{
//N : 거리에 있는 아이들 수
//M : 아이들의 친구 관계 수
//K : 울음 소리가 공명하기 위한 최소 아이수
static int N, M, K;
static int[] candy;
static List<List<Integer>> friends;
static boolean[] visited;
static List<int[]> groups;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
//한 아이의 사탕을 뺏으면 그 아이의 친구들의 사탕은 모두 뺏어버린다
//사탕을 뺏긴 아이는 운다
//K명의 아이가 울면 어른들이 나와버린다
candy = new int[N + 1];
friends = new ArrayList<>();
st = new StringTokenizer(br.readLine());
for(int i = 1; i <= N; i++) {
candy[i] = Integer.parseInt(st.nextToken());
friends.add(new ArrayList<>());
}
friends.add(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());
friends.get(a).add(b);
friends.get(b).add(a);
}
//*************입력 끝**********************
//뺏을 수 있는 사탕의 최대 개수 출력
//그룹 만들기
//[사람수, 사탕개수]
groups = new ArrayList<>();
visited = new boolean[N + 1];
for(int i = 1; i <= N; i++) {
makeGroup(i);
}
//K미만이어야 울지 않기 때문에 K보다 작아야함
int[] dp = new int[K]; //dp[i] = 사람의 수가 i일때 가질 수 있는 사탕 최대 개수
for(int i = 0; i < groups.size(); i++) {
for(int j = K - 1; j >= groups.get(i)[0]; j--) {
dp[j] = Math.max(dp[j], dp[j - groups.get(i)[0]] + groups.get(i)[1]);
}
}
System.out.println(dp[K - 1]);
}
static void makeGroup(int now) {
if(visited[now]) return;
Stack<Integer> stack = new Stack<>();
stack.push(now);
visited[now] = true;
int count = 1;
int sum = candy[now];
while(!stack.isEmpty()) {
int pop = stack.pop();
for(int i : friends.get(pop)) {
if(!visited[i]) {
stack.push(i);
visited[i] = true;
count++;
sum += candy[i];
}
}
}
groups.add(new int[]{count, sum});
}
}
접근 방법
단순 그래프 문제라고 생각했는데 DP를 사용해야한다.
먼저 dfs로 연결할 수 있는 친구들만큼 묶어서 그룹을 나눠줬다.
그룹을 나눌 때 해당 그룹에 있는 인원수, 해당 아이들에게서 뺏을 수 있는 사탕의 수를 list로 저장해주었다.
그뒤는 냅색알고리즘을 적용해서 인원 = kg 사탕 = value라고 생각하고 적용 시켰다.
최근 모 기업 코테에 냅색 나왔는데 백퍼센트 틀렸을거 같아 속상하여 냅색 많이 푸는중...ㅠㅠ