Closed KodaHye closed 3 weeks ago
2 <= N, M <= 50
N
: 주어지는 가족 정보의 수M
: 왕위 계승을 주장하는 사람의 수N
, 간선의 수: 2 × N
O(N + 2N)
3N
(최대 가능 사람 수)으로 설정HashMap<String, Integer> nameToIdx
: 이름을 idx
로 바꿔주는 HashMaphashMap<Integer, String> idxToName
: idx
를 이름으로 바꿔주는 변수double[] score
: 각 사람들의 혈통 점수를 저장하는 변수ArrayList<Integer>[] adj
: 인접 리스트 저장
idx
로 변환하고, idx
끼리 연결관계를 저장int[] degree
: 진입차수 배열 저장boolean[] select
: 왕위 계승을 주장하는 사람인지 저장solution()
idx
라면 혈통 점수를 1
로 설정idx
가 아니라면 혈통 점수를 0.5
로 설정while(!q.isEmpty())
1
씩 빼주면서 혈통 점수 update0
이라면 queue
에 넣어주기HashMap을 이용한 트리
트리 DP
라고 생각메모이제이션
하면서 자식의 혈통값을 찾아줌
private static double recursive(String person) {
// 미리 계산된 값이 있다면 반환 -> 메모이제이션
if (bloodMap.containsKey(person) && bloodMap.get(person) > 0) {
return bloodMap.get(person);
}
if (!tree.containsKey(person)) {
return 0;
}
String[] parents = tree.get(person);
double parent1Blood = recursive(parents[0]) / 2.0;
double parent2Blood = recursive(parents[1]) / 2.0;
double personBlood = parent1Blood + parent2Blood;
bloodMap.replace(person, personBlood); // 메모이제이션
return personBlood;
}
처음에 혈통값 넘겨주는 거 잘못 적어서 와장창 틀렸네요🐹
위상 정렬 문제였군요...😿
O(N+M)
가족구성도 만들기 (입력
)
family
해시맵에 자식(키) 부모(값)으로 정보 넣기가족구성도를 바탕으로 혈통 계산(cal()
)
info
: 사람 별 혈통 정보가장 혈통 가까운 후보자 찾기
저도 재귀로 풀었는데,, 위상정렬 문제이길래 위상정렬 버전으로도 도전해봤는데 자꾸 틀렸다고 하네요.....ㅠㅠ
fMap
: 자식 리스트를 나타내는 해시맵indegree
: 진입차수(= 부모수)를 나타내는 해시맵score
: 혈통 점수를 나타내는 해시맵String으로 입력되서 인덱스처리하는 거랑, 계승할 때 혈통 점수 무시해서 해멨습니다 ㅎㅎㅎㅎ
문제의 "다시 자식이 부모의 부모가 되는 경우도 없다. 또, 한 사람이 여러 명의 자식이 될 수 도 없다."
- 위상정렬은 방향만 있고, 사이클이 없는 그래프 특징을 가지고 있음
- 문제에서 부모와 자식간의 계층관계를 보면 부모 → 자식 방향이 있고, 부모 ← 자식 방향으로 사이클이 발생하지 않음
Map<String,ArrayList<String>> families = new HashMap<>()
하나의 자식에 부모가 속해있는<자식,자식의부모 리스트>
형태
Map<String,Double> bloodRatio = new HashMap<>()
자식의 혈통을 저장하는 곳으로 깊이탐색을 통해 계산되는 자식의 혈통이 갱신된다.위상정렬 이라는걸 처음알았는데, 진짜 어렵네요!?😧
ArrayList
자식의 부모 수 증가
parentCount.put(child, parentCount.getOrDefault(child, 0) + 2);
parentCount.putIfAbsent(parent1, 0);
parentCount.putIfAbsent(parent2, 0);
blood.putIfAbsent(child, 0L); // 자식의 초기 혈통 값은 0
blood.putIfAbsent(parent1, 0L); // 부모의 혈통 초기화
blood.putIfAbsent(parent2, 0L); // 부모의 혈통 초기화
while (!queue.isEmpty()) {
String current = queue.poll();
if (childMap.containsKey(current)) {
for (String child : childMap.get(current)) {
blood.put(child, blood.get(child) + blood.get(current) / 2); // 부모로부터 혈통을 물려받음
parentCount.put(child, parentCount.get(child) - 1); // 부모수 -1
if (parentCount.get(child) == 0) {
queue.add(child); // 부모가 모두 계산된 자식은 큐에 추가
}
}
}
}