BOJ 25206 (너의 평점은)

JH·2023년 8월 7일
0

BOJ 알고리즘 (C++)

목록 보기
86/97
post-custom-banner

  • 문제
    인하대학교 컴퓨터공학과를 졸업하기 위해서는, 전공평점이 3.3 이상이거나 졸업고사를 통과해야 한다. 그런데 아뿔싸, 치훈이는 깜빡하고 졸업고사를 응시하지 않았다는 사실을 깨달았다!

    치훈이의 전공평점을 계산해주는 프로그램을 작성해보자.

    전공평점은 전공과목별 (학점 × 과목평점)의 합을 학점의 총합으로 나눈 값이다.

    인하대학교 컴퓨터공학과의 등급에 따른 과목평점은 다음 표와 같다.


    P/F 과목의 경우 등급이 P또는 F로 표시되는데, 등급이 P인 과목은 계산에서 제외해야 한다.
    과연 치훈이는 무사히 졸업할 수 있을까?

  • 입력
    20줄에 걸쳐 치훈이가 수강한 전공과목의 과목명, 학점, 등급이 공백으로 구분되어 주어진다.

  • 출력
    치훈이의 전공평점을 출력한다.

    정답과의 절대오차 또는 상대오차가 10^-4이하이면 정답으로 인정한다.

  • 제한
    • 1 ≤ 과목명의 길이 ≤ 50
    • 과목명은 알파벳 대소문자 또는 숫자로만 이루어져 있으며, 띄어쓰기 없이 주어진다. 입력으로 주어지는 모든 과목명은 서로 다르다.
    • 학점은 1.0, 2.0, 3.0, 4.0중 하나이다.
    • 등급은 A+, A0, B+, B0, C+, C0, D+, D0, F, P중 하나이다.
    • 적어도 한 과목은 등급이 P가 아님이 보장된다.

#include<iostream>
#include<string>
using namespace std;
double totalCredit;;
double transferredGrade[20];
double answer;

void fast_io() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
}
class Major {
public:
	string subject;
	double credit;
	string grade;
};

void input(Major* m) {
	for (int i = 0; i < 20; i++) {
		cin >> m[i].subject >> m[i].credit >> m[i].grade;

		if (m[i].grade.size() > 1) {
			if (m[i].grade[0] == 'A') {
				transferredGrade[i] = 4.0;
			}
			else if (m[i].grade[0] == 'B') {
				transferredGrade[i] = 3.0;
			}
			else if (m[i].grade[0] == 'C') {
				transferredGrade[i] = 2.0;
			}
			else if (m[i].grade[0] == 'D') {
				transferredGrade[i] = 1.0;
			}
			else {

			}

			if (m[i].grade[1] == '+') {
				transferredGrade[i] += 0.5;
			}
			else {

			}
			
			totalCredit += m[i].credit;
		}
		else {
			if (m[i].grade[0] == 'F') {
				transferredGrade[i] = 0.0;
				totalCredit += m[i].credit;
			}
			else {
				transferredGrade[i] = -1.0;
			}
		}
	}
}

int main() {
	fast_io();
	Major majors[20];
	input(majors);
	double totalSum = 0.0;
	for (int i = 0; i < 20; i++) {
		if (transferredGrade[i] == -1.0) {
			continue;
		}
		double score = majors[i].credit * transferredGrade[i];
		totalSum += score;
	}
	answer = totalSum / totalCredit;
	cout << answer;

	return 0;
}

  입력의 크기가 20으로 제한되어 있어 시간 초과 관련해서는 딱히 신경쓸게 없었다. 과목명, 학점, 성적을 입력받기 위해 Major이라는 Class를 설계하였지만 과목 명은 딱히 문제에서 사용되지 않기 때문에 Class 설계까지는 굳이 할 필요는 없어보이긴 한다.

문제에서 성적을 학점으로 바꾸는 것과 Pass 과목은 성적 산출 시 포함시키지 않는 것이 핵심이다. 성적의 입력이 2글자로 제한되어있기 때문에 F와 P를 제외한 성적은 첫번째 글자로 1,2,3,4를 정한 후 뒤에 + 유무에 따라 0.5점을 더해주는 방식을 사용하여 분기를 최소화 시키려고 노력했다.

Pass인 과목 부분을 합산하지 않기 위해 -1로 두어 나중에 구분할 수 있도록 하였다.

시간 복잡도 : O(N)


숏코딩
#include <iostream>
int main() {
	char S[51], G[3];
	int i = 0;
	double m = 0, s = 0, g, c;
	for (; i < 20; i++) {
		std::cin >> S >> g >> G;
		if (G[0] == 'P') continue;
		c = 'E' - G[0];
		if (c < 0) c = 0;
		else if (G[1] == '+') c += 0.5;
		s += g; m += g * c;
	}
	std::cout << m / s;
}

학점을 숫자로 변환하는 과정에서 'E'-입력받은 첫번째 알파벳으로 학점을 바꾸는 부분이 분기를 하지 않아도 되어 매우 효율적으로 보인다. (F가 나오면 음수를 캐치에서 0으로 변환)

profile
블로그 -> 노션
post-custom-banner

2개의 댓글

comment-user-thumbnail
2023년 8월 7일

공감하며 읽었습니다. 좋은 글 감사드립니다.

1개의 답글