본문 바로가기
CNU 학습 동아리/2020 동계 학습 동아리

2020 동계 학습 동아리_6회차_2020-02-14(금)

by 매화of사군자 2020. 2. 14.

목표 : 카카오 코드 페스티벌 2018 예선 E, F번 풀기

https://www.acmicpc.net/problem/15957

 

15957번: 음악 추천

입력의 첫째 줄에는 세 정수로, 곡의 수 N(2 ≤ N ≤ 100,000), 추천 알고리즘의 결과 데이터의 수 K(1 ≤ K ≤ 100,000), 목표 점수 J(10 ≤ J ≤ 108)가 주어진다. 각각의 곡은 1번부터 N번까지 번호가 붙어 있다. 다음 줄에 N-1개의 곡 번호가 주어지는데, 이는 2번 곡부터 해당 곡의 부모 노드가 되는 곡의 번호이다. 1번 곡은 부모 노드가 없다. 다음 줄에 N개의 수가 주어지는데, 이는 1번 곡부터 해당 곡을 부른 가

www.acmicpc.net

해결 방법

> 입력을 받아 트리를 그린다.

> 각 노드의 서브트리의 노드 개수를 구한다.(가중치를 나누기 위함)

> dfs를 돌면서 가중치를 적용시킨다.

> 트리를 순회하면서 가중치가 목표 점수에 도달하면 걸린시간을 체크한다.

 

결과

> 시간 초과

> 내가 생각한 이유 : 노드의 개수가 10만개인데 내가 짠 코드는 dfs를 10만번 돌고 또 돌아야 하기 떄문에 시간초과가 난 것 같다.

 

코드

더보기

import sys

from collections import defaultdict

 

sys.setrecursionlimit(10 ** 6)

 

def DFS_visit(adjuvisited):

    if num_subnode[u] != None:

        return

    visited.append(u)

    for v in adj[u]:

        if v not in visited:

            DFS_visit(adj, v, visited)

 

def DFS(adjs):

    visited =[]

    DFS_visit(adj, s, visited)

    num_subnode[s] = len(visited)

 

def DFS_visit_cal(adjuvisitedtimew):

    visited.append(u)

    index = result[u - 1][2] - 1

    if not check[index]:

        result[u - 1][1] += w

        if (result[u - 1][1] // singer_count[result[u - 1][2]]) >= target_score:

            check[index] = True

            output[result[u - 1][2]] = time

    for v in adj[u]:

        if v not in visited:

            DFS_visit_cal(adj, v, visited, time, w)

 

def DFS_cal(adjstimew):

    visited =[]

    DFS_visit_cal(adj, s, visited, time, w)

 

musictree = defaultdict(set)

num_music, num_data, target_score = map(intinput().split())

parent_node = list(map(intinput().split()))

parent_node.insert(0,0)

 

#가수 처리

singer = list(map(intinput().split()))

singer_count = defaultdict(int)

for i in singer:

    singer_count[i] += 1

 

for i in range(1, num_music + 1):

    for j in range(num_music):

        if parent_node[j] == i:

            musictree[i].add(j + 1)

 

num_subnode = list(None for i in range(num_music + 1))  #서브트리의 노드 개수

for i in range(1, num_music + 1):

    DFS(musictree,i)

 

result = list()

for i in range(num_music):

    result.append([0,0,singer[i]])    #시간, 가중치, 가수

 

check = [False for i in range(num_music)]

output = defaultdict(lambda: -1)

 

for i in range(num_music):

    time, subtree, weight = map(intinput().split())

    DFS_cal(musictree, subtree, time, weight//num_subnode[subtree])

 

for i in singer:

    print(output[i])

https://www.acmicpc.net/problem/15958

 

15958번: 프로도의 100일 준비

입력의 첫째 줄에는 직각다각형의 꼭짓점의 개수 N(4 ≤ N ≤ 500,000)이 주어진다. 이어지는 N줄 각각엔 직각다각형 꼭짓점의 좌표를 나타내는 정수 (x, y) (0 ≤ x, y ≤ 109)가 공백을 사이에 두고 주어진다. 입력 다각형의 시작점은 원점 (0,0)이고, 꼭짓점이 시계방향 순서로 주어진다. 즉, 연속하는 두 개의 꼭짓점은 직각다각형의 한 선분을 이루며, x좌표는 단조증가한다. 참고로, 시작점과 끝점만 y좌표가 0이다. 연속하는 세 점이

www.acmicpc.net

해결 방법

> 히스토그램을 y축의 변화를 기준으로 직사각형으로 나눈다.

> x변의 최대값과 y변의 최솟값을 구한다.

> 조건을 달아 연산하면 될 것 같다.

 

음악추천에 시간을 너무 많이 써서 위의 단계에서 끝났다.

댓글