developer-ellen
인간 디버거의 로그 찍기
developer-ellen
전체 방문자
오늘
어제
  • 분류 전체보기 (217)
    • 회고록 (0)
    • 취뽀 및 커리어 여정의 Stack (2)
      • SSAFY 7기 (2)
    • 프로그래밍공부 (24)
      • c++ (0)
      • JAVA (3)
      • Spring (5)
      • design pattern (3)
      • BackDB (1)
      • Servlet&JSP (3)
      • Vue (4)
      • JPA (4)
      • Infra (1)
      • Linux (0)
    • AI (3)
      • papers (3)
      • trend (0)
    • 프로젝트진행 (0)
      • 데이터베이스 (0)
      • 서버개발 (0)
      • 인공지능 (0)
      • 하루정리 (0)
    • 포트폴리오 (0)
    • 알고리즘 (158)
      • 알고리즘문풀 (155)
      • 알고리즘공부 (3)
    • 통계공부 (15)
      • 시계열분석 (15)
      • 회귀분석 (0)
    • CS (14)
      • 컴퓨터네트워크 (4)
      • 운영체제 (8)
      • 데이터베이스 (2)
    • 주저리주저리 (0)
      • 필사 (0)
    • 취업관련정보 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 삼성코테파이썬풀이
  • ARIMA모형
  • 시계열
  • 삼성코테파이썬준비
  • 운영체제인터럽트
  • 삼성코테파이썬
  • 시계열분석
  • 삼성코테기출
  • 삼성코테구현문제추천
  • 삼성코테구현풀이
  • BOJ파이썬풀이
  • AR모형
  • MA모형
  • 삼성코테자바꿀팁
  • c++ 빌더 패턴
  • 코테파이썬
  • 삼성코테준비
  • 백준파이썬풀이
  • SW역량테스트파이썬풀이
  • 카카오코테
  • c++디자인패턴
  • Arima
  • 통계학
  • 카카오코테java풀이
  • 삼성코테자바준비
  • 삼성코테자바풀이
  • 삼성코테기출자바풀이
  • 데이터분석
  • SW역량테스트파이썬
  • 통계분석

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

알고리즘/알고리즘문풀

2021 KAKAO BLIND RECRUITMENT - 매출 하락 최소화 (JAVA)

2022. 6. 9. 00:21

❓ 문제 - 2021 KAKAO BLIND RECRUITMENT 매출 하락 최소화 - JAVA 풀이법

출처 

(https://programmers.co.kr/learn/courses/30/lessons/72416)

 

코딩테스트 연습 - 매출 하락 최소화

CEO를 포함하여 모든 직원은 팀장 또는 팀원이라는 직위를 가지고 있으며 그림에서는 팀장과 팀원의 관계를 화살표로 표시하고 있습니다. 화살표가 시작되는 쪽의 직원은 팀장, 화살표를 받는

programmers.co.kr

 

 

📝 문제해결법 

1. Tree DP로 해결해야한다.

 

우선, Tree DP 에서 Top-down 방식으로 루트 노드부터 dp에 최소화된 매출액의 합 생각했는데..

다른 노드로 갈 수록 고려해야할 사항이 많아져서.. 식을 유도하지 못 했다.

 

카카오 풀이를 먼저 찾아봤는데 

 

최적의 해는 DFS로 방문한 순서의 역방향으로 차례대로 결정이 되며, 리프 노드에 대한 최적해가 처음에 정해지고, 마지막에야 비로소 1번 루트 노드에 대한 최적해를 구할 수 있습니다.

 

d[i][0] : i번 노드가 루트인 서브트리에서, i번 노드가 워크숍에 불참하는 경우의 최적해

d[i][1] : i번 노드가 루트인 서브트리에서, i번 노드가 워크숍에 참석하는 경우의 최적해

 

라고 bottom-up 방식을 통해서 접근해야 최적해를 dp에 저장할 수 있다.

 

(https://loosie.tistory.com/188) 분의 풀이를 참고해서 코드를 작성했다.

 

중요한 흐름은 연결된 자식 노드가 있는 서브트리까지 dfs를 타고 들어간 다음에

서브 트리 내 루트를 기준으로 자기 자신을 참석시킬 때의 최적해와

자기 자신을 참석시키지 않을 떄의 최적해를 dp에 저장한다.

 

이때, 경우의 수를 나눠서 따져야 하는데

 

1) 서브트리의 루트노드가 참석할 경우, 서브트리의 자식 노드가 참석하지 않을 경우

2) 서브트리의 루트노드가 참석할 경우, 서브트리의 자식 노드가 참석할 경우

3) 서브트리의 루트노드가 참석하지 않을 경우, 서브트리의 자식 노드가 참석할 경우

 

이런 경우만을 고려해서 최소화된 매출액의 합을 구해야 한다.

 

if(dp[child][0] < dp[child][1]) {
				dp[idx][0] += dp[child][0];
				dp[idx][1] += dp[child][0];
				
				extra = Math.min(extra, dp[child][1] - dp[child][0]);
		} else {
				
				dp[idx][0] += dp[child][1];
				dp[idx][1] += dp[child][1];
				
				extra = 0;
	}

 

이 부분이 위 경우를 고려한 코드인데,

 

만약 연결된 자식 노드가 포함되지 않았을 때가 최적해를 가진다면

해당 경우를 현재 서브 트리의 루트 노드에 더해준다.

 

만약 dp[idx][0] ->

즉 서브 트리의 루트노드도 참석하지 않고, 자식 노드 모두 다 참석하지 않으면

주어진 조건에서 벗어난다. 

따라서 루트노드가 참석하지 않을 때는 자식 노드들 중에서 한 자식 노드라도 참석해야하므로

자식 노드들 중에서 참석했을 때 가장 최적해를 가지는 경우를 extra에 최솟값 갱신을 통해 구한 뒤  

extra를 dp[idx][0]에 더해준다.

 

 

또한 extra에 왜 dp[child][0]을 빼주는가 했을 때 앞에서 이미 dp[idx][0]에 dp[child][0]을 더해줬기 때문이다.

 

 

2. 느낀점

 

막상 풀이를 찾고 해결해보니

(https://developer-ellen.tistory.com/152) 의 백준에 대기업 승범이네라는 문제랑 유사했다!

Tree DP 문제를 더 많이 풀어봐서 

여러 조건일 때도 코드를 구현할 수 있게 실력을 키워야겠다.

 

 

💻 소스코드 

import java.util.ArrayList;

public class Solution {
	public static ArrayList<ArrayList<Integer>> link;
	public static int[][] dp = new int[300001][2];
	public static void main(String[] args) {
		int a = solution(new int[]{14, 17, 15, 18, 19, 14, 13, 16, 28, 17}, 
				new int[][]{{10, 8}, {1, 9}, {9, 7}, {5, 4}, {1, 5}, {5, 10}, {10, 6}, {1, 3}, {10, 2}}
				);
	
		System.out.println(a);
	}
	
	public static int solution(int[] sales, int[][] links) {
		link = new ArrayList<>();
		
		for(int i=0;i<sales.length+1;i++) {
			link.add(new ArrayList<>());
		}
		
		for(int i=0;i<links.length;i++) {
			int a = links[i][0];
			int b = links[i][1];
			link.get(a).add(b);
		}
		
		dfs(sales, 1);
		int answer = Math.min(dp[1][0], dp[1][1]);
		return answer;
	}
	
	public static void dfs(int[] sales, int idx) {
		dp[idx][0] = 0;
		dp[idx][1] = sales[idx-1];
		
		if(link.get(idx).size() == 0) return;
		int extra = (int)1e9;
		for(int child:link.get(idx)) {
			dfs(sales, child);
			
			if(dp[child][0] < dp[child][1]) {
				dp[idx][0] += dp[child][0];
				dp[idx][1] += dp[child][0];
				
				extra = Math.min(extra, dp[child][1] - dp[child][0]);
			} else {
				
				dp[idx][0] += dp[child][1];
				dp[idx][1] += dp[child][1];
				
				extra = 0;
			}
		}
		
		dp[idx][0] += extra;
		return;
	}

}

 

 

'알고리즘 > 알고리즘문풀' 카테고리의 다른 글

2022 KAKAO BLIND RECRUITMENT - 주차 요금 계산 (JAVA)  (0) 2022.06.15
2022 KAKAO BLIND RECRUITMENT - 신고 결과 받기 (JAVA)  (0) 2022.06.12
BOJ - 트리의 지름 1167번 (JAVA)  (0) 2022.06.08
2021 KAKAO BLIND RECRUITMENT - 합승 택시 요금 (JAVA)  (0) 2022.06.02
BOJ - 인내의 도미노 장인 호석 20165번 (JAVA)  (0) 2022.06.02
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • 2022 KAKAO BLIND RECRUITMENT - 주차 요금 계산 (JAVA)
    • 2022 KAKAO BLIND RECRUITMENT - 신고 결과 받기 (JAVA)
    • BOJ - 트리의 지름 1167번 (JAVA)
    • 2021 KAKAO BLIND RECRUITMENT - 합승 택시 요금 (JAVA)
    developer-ellen
    developer-ellen

    티스토리툴바