Algorithm

백준 - 17831번(머기업 승범이네) / C++

wizi 2021. 3. 10. 14:04

www.acmicpc.net/problem/17831

 

17831번: 대기업 승범이네

첫 번째 줄에 판매원들의 수 N(2 ≤ N ≤ 200,000)이 주어진다. 판매원들은 1번, 2번, …, N번으로 번호가 매겨지며, 승범이는 항상 1번이다. 두 번째 줄에 2번 판매원부터 N번 판매원의 사수가 순서대

www.acmicpc.net

문제 제목을 봤는데 친구가 사업에 성공했나보다. 속초사는 친구였는데 잘되어서 서울에서 왕부자가 되었다.

이 문제는 2019 홍익대학교 프로그래밍 경진대회 문제였다.

 

알고리즘 분류 : 트리에서의 다이나믹 프로그래밍.

 

풀이과정:

dp[MAX][2]를 사용하여

dp[i][0]에는 현 멘토노드를 선택하지 않은경우,

dp[i][1]에는 현 멘토노드를 선택한 경우로 최댓값을 저장하였다.

 

필자의 경우 현재 보고있는 멘토노드를 기준으로 코드를 작성하였다.

대기업 승범이네의 주인공 승범이가 작성한 코드를 보니 멘티노드 기준으로 작성해도 된다.

 

점화식은 2개로 나누어진다.

1. dp[i][0] 의 경우 현 멘토노드를 선택하지 않았으므로 

i노드의 자식노드를 k라고 할 때 ∑max(dp[k][0],dp[k][1]) 을 더해주고 리턴하면 된다.

 

2. dp[i][1] 의 경우 현 멘토노드를 선택한 것이므로 멘티 노드들 중 하나만 선택해야한다.

   1) i의 모든 자식노드 k에 대해서

   dp[k][0] < dp[k][1]  만족하는 모든 dp[k][1]의 값을 더해 놓는다.  이것을 sum_dp_1 이라고하자.

   dp[k][0] >= dp[k][1] 만족하는 모든 dp[k][0]의 값을 더해 놓는다. 이것을 sum_dp_0이라고 하자.

 

두가지 경우를 각각 나눈 이유는 현 멘토노드를 골랐을 때 자식노드가 이미 선택이 되었냐, 

선택이 되지 않았냐에 따라 점화식이 달라지기 때문이다.

 

만약 멘티노드가 선택된경우 = sum_dp_1 + sum_dp_0 - dp[k][1] + cost[curnode] * cost[nextnode] 이고

만약 멘티노드가 선택되지 않은경우 = sum_dp_1 + dum_dp_0 + cost[curnode] * cost[nextnode] 이다.

 

이를 통해 top_down dp구조로 만들면된다.

그리고 leaf_node일 경우 선택하던 안하던 0을 리턴해준다.

 

비고 - 다른사람들 코드를 보니 코드를 더 깔끔하게 짤 수 있다. 점화식을 깔끔하게 정리할 수 있다.

 

코드