[프로그래머스] 다단계 칫솔 판매

이강혁·2024년 11월 5일
0

프로그래머스

목록 보기
77/82

https://school.programmers.co.kr/learn/courses/30/lessons/77486

다단계에서 칫솔 판매하는데 상급자에게 수익의 10%를 반올림한 것을 바쳐야하는 구조이다. 판매 실적이 주어질 때 수익이 어떻게 되는지 찾는 문제이다.

Python

1차 시도 - 실패

def solution(enroll, referral, seller, amount):
    answer = []
    
    tree = dict()
    rev = dict()
    sell = dict()
    level = dict()
    for e in enroll:
        tree[e] = list()
        rev[e] = 0
        sell[e] = 0
        level[e] = 0
    
    for idx, r in enumerate(referral):
        if r != "-":
            tree[r].append(enroll[idx])
    
    for idx, s in enumerate(seller):
        sell[s] = amount[idx] * 100
    

    # root 찾기
    for e in enroll:
        que = [(e, 0)]
        idx = 0
        while idx < len(que):
            now, lev = que[idx]
            idx += 1
            for next in tree[now]:
                que.append((next, lev+1))
        for q, l in que:
            level[q] = max(level[q], l)
    tree["center"] = []
    rev["center"] = sell["center"] = 0
    
    for e, l in level.items():
        if l == 0:
            tree["center"].append(e)
            
    def dfs(now):    
        cost = [sell[now]]
        
        for next in tree[now]:
            cost += dfs(next)
        s = 0
        for idx, c in enumerate(cost):
            s += c - int(c / 10)
            cost[idx] = int(c / 10)
        
        rev[now] = s
        
        return cost
    dfs("center")
    for e in enroll:
        answer.append(rev[e])
    
    return answer

DFS로 수익을 계산하는 것이 낫겠다 판단했다. 탐색하면서 하급자들이 얻은 수익을 cost라는 리스트에 추가해주었다.
모든 하급자 탐색이 끝나면 cost를 돌면서 10%의 수익을 뗀 나머지를 s에 더하고 cost에는 10%의 수익을 저장했다.
결과적으로 본인은 s만큼의 수익을 얻게되고 rev에 저장한 후, 상급자에게 cost를 반환해준다.

이렇게 하기 위해서 root를 찾을 필요가 있었다. input에는 root가 주어지지 않았기에 bfs를 통해서 각 사람의 level을 측정하고, 모든 탐색이 끝난 후 level이 0인 사람을 추려서 root의 자식으로 넣어주었다.

문제에 주어진 테스트케이스는 통과하였는데 제출하니까 실패했다. 심지어 마지막 3개의 테스트 케이스는 런타임 에러가 발생하기도 했다.

2차 시도

def solution(enroll, referral, seller, amount):
    rev = [0] * len(enroll)
    
    enum = dict()
    for i, e in enumerate(enroll):
        enum[e] = i
    
    for idx, s in enumerate(seller):
        money = amount[idx] * 100
        while s != "-" and money > 0:
            i = enum[s]
            rev[i] += money - money//10
            money //= 10
            s = referral[i]
    
    return rev

다른 풀이를 참고해서 해결했다. 트리 모양만 보고 너무 복잡하게 접근했던 것 같다.
enroll의 index를 따로 저장해줄 딕셔너리를 만들어줬다. 그리고 seller를 돌면서 해당 seller의 판매금을 구해서 money에 저장해주었다.

while문을 통해서 상급자에게 떼줄 10%를 제한 나머지를 본인의 수익인 rev에 더해주었고, 상급자에게 떼줄 10%를 money에 저장한 뒤 referral에서 상급자를 찾았다.

순간 상급자가 없는 referral이 "-"인 사람일 때 money는 어떻게 되지라고 고민했으나 center에 수익이 몰리기에 상관이 없다는 것을 깨달았다.

tree를 본다고 무조건 평소에 쓰던 bfs, dfs 혹은 다익스트라나 기타 등등의 알고리즘이 정답이라는 생각은 버려야겠다.

profile
사용자불량

0개의 댓글