본문 바로가기
Data Structures and Algorithms/백준 온라인 저지

백준 온라인 저지 | 10825번 국영수 | C++

by continue96 2022. 7. 24.

백준 온라인 저지 | 10825번 국영수 | C++

 

10825번: 국영수

첫째 줄에 도현이네 반의 학생의 수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 한 줄에 하나씩 각 학생의 이름, 국어, 영어, 수학 점수가 공백으로 구분해 주어진다. 점수는 1보다 크거나 같고, 1

www.acmicpc.net

 

1. 문제 접근

 1.1 tuple 자료 구조

 학생마다 이름과 국어, 영어, 수학 점수가 주어진다. 구조체(structure)를 사용하여 네 가지 데이터를 다룰 수도 있지만, 조금 더 편리한 tuple 자료 구조를 사용하려고 한다. #include <tuple> 헤더 파일을 선언하고 이름과 국어, 영어, 수학 점수를 저장하는 데 가장 적절한 타입인 <string, int, int, int>로 데이터를 받는다.

 

 1.2 compare 사용자 정의 정렬

 단순 오름차순, 내림차순이 아닌 주어진 조건에 맞도록 정렬하려면 compare 함수를 사용해야 한다. 비교할 tuple 자료 구조 a, b를 인자로 선언한다. 이때 compare 함수에 전달되는 두 인자 a, b는 const 참조로 선언하여 불필요한 복사로 인해 성능이 떨어지지 않도록 한다. compare 함수에서 오름차순(증가하는 순서)은 a < b를 반환하고 내림차순(감소하는 순서)은 a > b를 반환해야 한다.

 

2. 문제 풀이

  1. 학생 정보를 저장할 info 벡터를 정의하고 tuple 자료 구조로 학생 정보를 받아 info 벡터에 저장한다.
  2. sort 함수로 info 벡터를 정렬한다.
    • 모든 점수가 같으면 이름 사전 순으로 증가하는 순서로 → a.이름 < b.이름
    • 국어 점수와 영어 점수가 같으면 수학 점수가 감소하는 순서로 → a.수학 > b.수학
    • 국어 점수가 같으면 영어 점수가 증가하는 순서로 → a.영어 < b.영어
    • 모든 점수가 다르면 국어 점수가 감소하는 순서로  → a.국어 > b.국어

 

3. 문제 해결

#include <iostream>
#include <algorithm>
#include <vector>
#include <tuple>
using namespace std;

bool compare(const tuple<string, int, int, int>& a, const tuple<string, int, int, int>& b);
int N;

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	cin >> N;
	vector<tuple<string, int, int, int>> info(N);

	// 학생 수만큼 이름, 국어, 영어, 수학 점수를 받습니다.
	for (int i = 0; i < N; ++i) {
		string name;
		int korean, english, math;
		cin >> name >> korean >> english >> math;
		info[i] = { name, korean, english, math };
	}

	// 비교 함수에 근거하여 배열을 정렬합니다.
	sort(info.begin(), info.end(), compare);
	for (const auto& e : info) {
		cout << get<0>(e) << '\n';
	}
	return 0;
}

// 주어진 조건에 맞도록 배열을 정렬합니다.
bool compare(const tuple<string, int, int, int>& a, const tuple<string, int, int, int>& b) {
	if (get<1>(a) == get<1>(b)) {
		if (get<2>(a) == get<2>(b)) {
			if (get<3>(a) == get<3>(b)) {
				// 모든 점수가 같으면 이름이 사전 순으로 증가하는 순서로 정렬합니다.
				return get<0>(a) < get<0>(b);
			}
			// 국어와 영어 점수가 같으면 수학 점수가 감소하는 순서로 정렬합니다.
			return get<3>(a) > get<3>(b);
		}
		// 국어 점수가 같으면 영어 점수가 증가하는 순서로 정렬합니다.
		return get<2>(a) < get<2>(b);
	}
	// 국어 점수가 감소하는 순서로 정렬합니다.
	return get<1>(a) > get<1>(b);
}

 

4. 문제 고찰

4.1 tuple 자료 구조

 tuple 자료 구조는 pair 자료 구조를 확장한 것으로 여러 가지 데이터를 묶음으로 처리할 수 있다. 예를 들어, 3차원 공간에서의 (x, y, z) 좌표를 저장하거나, 사람의 이름, 나이, 성적과 같은 개인 정보를 저장하는 데 유용하다. tuple 자료 구조는 #include <tuple> 헤더 파일을 선언해야 사용할 수 있다. tuple 자료 구조에 저장된 데이터는 두 가지 방법으로 접근할 수 있는데, 일반적으로 get<>() 함수를 사용하나 C++17 이상인 경우, 구조적 바인딩으로 tuple 자료 구조의 데이터에 각각 접근할 수 있다.

#include <tuple>
tuple<int, double, string> t;
t = { 10, 10.0, "10" };

// get<>() 함수로 데이터에 접근할 수 있습니다.
int i = get<0>(t);
double d = get<1>(t);
string s = get<2>(t);

// C++17 이상은 구조적 바인딩으로 데이터에 접근할 수 있습니다.
auto& [i, d, s] = t;

 코딩 테스트에서 C++17을 지원하지 않는 경우, 구조적 바인딩을 사용할 수 없기 때문에 get<>() 함수를 명확하게 숙지하도록 하자.

댓글