[백준] solved.ac #18110

이지성·2024년 3월 3일

코딩테스트

목록 보기
7/8

문제 링크 : https://www.acmicpc.net/problem/18110


1. Constraints (제한 사항)

  • 알고리즘 문제와 요구와 제한사항

문제

너무 길다

입력

첫 번째 줄에 난이도 의견의 개수 n이 주어진다. (0 ≤ n ≤ 3 × 105)
이후 두 번째 줄부터 1 + n번째 줄까지 사용자들이 제출한 난이도 의견 n개가 한 줄에 하나씩 주어진다. 모든 난이도 의견은 1 이상 30 이하이다.

출력

solved.ac가 계산한 문제의 난이도를 출력한다.

제한

시간 제한 = 1초
메모리 제한 = 1024MB

주의할 점

  1. 의견이 없으면 난이도는 0이다
  2. 절사평균을 계산할 때는 반올림한다.
  3. 모든 난이도는 1 이상 30 이하이다.

2. Ideas (문제 풀이 방식)

  • 문제를 해결할 수 있는 방법 (최대 3개) + 시간/공간 복잡도

(1) 난이도 개수 세기

: 모든 난이도의 개수를 센다. 그리고 절사평균한 갯수를 배열에서 맨 앞과 뒤에서 뺀다. 빼고 난 다음 인덱스와 갯수를 곱해 난이도를 계산한다.

시간 복잡도 : O(N) -> 입력용
공간 복잡도 : O(N)


3. Code (작성한 코드)

  • 아이디어에서 다룬 내용을 바탕으로 구현한 코드
def solved_ac(n: int) -> float:
    level_cnt = [0] * 30
    
    for i in range(n):
        level = int(input())
        level_cnt[level-1] += 1
        
    cut_num = round(n * 0.15)
    
    cut_cnt, index = 0, 0   # 하위 15% 절삭 
    
    while cut_cnt < cut_num:
        if level_cnt[index] < cut_num:
            cut_cnt += level_cnt[index]
            level_cnt[index] = 0
            index += 1
        else:
            level_cnt[index] -= (cut_num - cut_cnt)
            break
        
    cut_cnt, index = 0, 29   # 상위 15% 절삭
    
    while cut_cnt < cut_num:
        if level_cnt[index] < cut_num:
            cut_cnt += level_cnt[index]
            level_cnt[index] = 0
            index -= 1
        else:
            level_cnt[index] -= (cut_num - cut_cnt)
            break
              
    return sum([level_cnt[i] * (i+1) for i in range(30)]) / (n - 2*cut_num)

n = int(input())
print(round(solved_ac(n)))
        

4. 다시 생각하기

  1. 0에 대한 코드를 넣지 않아서 zerodivision 오류가 떠서 고쳤다.
  2. cut_num - cnt_cnt보다 작거나 같아야하는데 cut_num보다 작으면이라 해서 값이 초과되는 경우를 제거하였다.
  3. 파이썬에서 round 함수가 0.5를 0으로 반환하는 걸 보고 욕을 하면서 코드를 고쳤다.
import math

def new_round(num: float) -> int:
    if num - int(num) >= 0.5:
        return math.ceil(num)
    else:
        return math.floor(num)

def solved_ac(n: int) -> float:
    if n == 0: return 0 # 다시 생각하기 1
    
    level_cnt = [0] * 30
    
    for i in range(n):
        level = int(input())
        level_cnt[level-1] += 1
        
    cut_num = new_round(n * 0.15)
    
    cut_cnt, index = 0, 0   # 하위 15% 절삭 
    
    while cut_cnt < cut_num:
        if level_cnt[index] <= cut_num - cut_cnt: # 다시 생각하기 2
            cut_cnt += level_cnt[index]
            level_cnt[index] = 0
            index += 1
        else:
            level_cnt[index] -= (cut_num - cut_cnt)
            break
        
    cut_cnt, index = 0, 29   # 상위 15% 절삭
    
    while cut_cnt < cut_num:
        if level_cnt[index] <= cut_num - cut_cnt: # 다시 생각하기 2
            cut_cnt += level_cnt[index]
            level_cnt[index] = 0
            index -= 1
        else:
            level_cnt[index] -= (cut_num - cut_cnt)
            break
        
    return sum([level_cnt[i] * (i+1) for i in range(30)]) / (n - 2*cut_num)

n = int(input())
print(new_round(solved_ac(n)))


마무리

round가 0.5를 0으로 뱉어내는 건 너무한 거 아닌가요? ㅋㅋㅋ

profile
FROM NOOBY TO RUBY

0개의 댓글