[BOJ 18110] - solved.ac (수학, 정렬, C++, Python)

보양쿠·2023년 6월 27일
0

BOJ

목록 보기
144/252

BOJ 18110 - solved.ac 링크
(2023.06.27 기준 S4)

문제

난이도 의견이 없다면 난이도는 0, 아니면 모든 사람의 난이도 의견의 30% 절사평균이 난이도가 된다.
n개의 난이도 의견이 1 이상 30 이하로 주어질 때, 난이도 출력

알고리즘

절사평균을 구하기 위해 정렬반올림

풀이

30% 절사평균은 위, 아래에서 15%를 제외해야 한다. 문제에서 실수 부분은 반올림해야 한다고 적혀있다. (물론, 사사오입)
그러므로 15%를 구하기 위해선 기준점 t를 round(n * (15 / 100) = n * 3 / 20)로 잡고
이를 정렬된 난이도 의견들에서 t부터 n - t + 1 (0-based index)까지의 합을 구해 총 개수인 n - t * 2로 나누어 round 함수를 적용하면 절사평균이 나온다.

주의사항

Python의 반올림 기본 방식은 오사오입이다.

  • 오사오입
    반올림에서 5 미만의 숫자는 버림하며 5 초과의 숫자는 올림한다. 5의 경우에는 5의 앞자리가 홀수인 경우엔 올림을 하고 짝수인 경우엔 버림을 하여 짝수로 만들어준다. 예를 들어 53.45는 53.4로, 32.75는 32.8로 반올림한다. 이를 오사오입(round-to-nearest-even)이라고 한다. 자연과학 및 공학의 유효 숫자에서 많이 쓴다.
    참고 링크

그렇다면 사사오입을 사용하기 위해선?

  1. decimal 모듈 사용
    decimal 정확한 십진법 사용을 위한 하나의 모듈인데 여기서 반올림 방식을 직접 지정할 수 있고 이는 type이 decimal.Decimal인 변수에 적용 가능하다.
    단점은 너무 느리다. 그러므로 이는 반올림뿐만 아니라 정확한 실수 부분의 표현이 필요할 때 사용하자.
import decimal
decimal.getcontext().rounding = decimal.ROUND_HALF_UP # 반올림

print(round(0.5), round(1.5), round(1.45, 1))
# output : 0 2 1.4
print(round(decimal.Decimal('0.5'), 0), round(decimal.Decimal('1.5'), 0), round(decimal.Decimal('1.45'), 1))
# output : 1 2 1.5
  1. 5e-(반올림하고자 하는 소수점 자리 + 1) 더해서 버림하기
    만약 정수 부분까지 반올림하고자 하면 5e-(0 + 1) = 5e-1 = 0.5를 더해서 버림하면 된다.
    사사오입 반올림만을 위한다면 이 방법이 제일 간단하고 빠르다.
print(round(0.5), round(1.5), round(1.45, 1))
# output : 0 2 1.4
print(round(0.5 + 5e-1), round(1.5 + 5e-1), round(1.45 + 5e-2, 1))
# output : 1 2 1.5

코드

  • C++
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n; cin >> n;

    // 아직 아무 의견이 없다면 문제의 난이도는 0으로 결정한다.
    if (!n){
        cout << 0;
        return 0;
    }

    // 의견이 하나 이상 있다면, 문제의 난이도는 모든 사람의 난이도 의견의 30% 절사평균으로 결정한다.
    int a[n]; for (int i = 0; i < n; i++) cin >> a[i]; sort(a, a + n);
    int t = round((float)(n * 3) / 20); // 15%

    // 위, 아래에서 15%를 제외한 평균
    int s = 0; for (int i = t; i + t < n; i++) s += a[i];
    int m = round((float)s / (n - t * 2));
    cout << m;
}
  • Python
n, *a = map(int, open(0))

# 아직 아무 의견이 없다면 문제의 난이도는 0으로 결정한다.
if not n:
    print(0)
    exit()

# 의견이 하나 이상 있다면, 문제의 난이도는 모든 사람의 난이도 의견의 30% 절사평균으로 결정한다.
# round 함수는 오사오입이므로 0.5를 더해 버림하는 방식을 사용하자.
t = int(n * 3 / 20 + 0.5) # 15%
m = int(sum(sorted(a)[t:n - t]) / (n - t * 2) + 0.5) # 위, 아래에서 15%를 제외한 평균
print(m)
profile
GNU 16 statistics & computer science

0개의 댓글