https://www.acmicpc.net/problem/2535
2535번: 아시아 정보올림피아드
첫 번째 줄에는 대회참가 학생 수를 나타내는 N이 주어진다. 단, 3 ≤ N ≤ 100이다. 두 번째 줄부터 N개의 줄에는 각 줄마다 한 학생의 소속 국가 번호, 학생 번호, 그리고 성적이 하나의 빈칸을 사
www.acmicpc.net
🔷 알고리즘 분류 - 수학, 정렬 난이도 - 실버 5
collections 모듈의 defaultdict는 파이썬의 내장 딕셔너리(dict)와 비슷한데, 차이점은 키(key)가 존재하지 않을 때 미리 지정해 둔 초기값을 반환한다는 점입니다.
일반적인 딕셔너리에서는 존재하지 않는 키를 호출하면 KeyError가 발생합니다.
하지만 defaultdict를 사용하면, 존재하지 않는 키를 호출해도 미리 설정해 둔 초기값을 반환하여 KeyError를 방지합니다.
기본적인 사용법은 다음과 같습니다.
from collections import defaultdict
# 문자열을 선언합니다.
s = 'Hello, World!'
# defaultdict를 선언합니다. 기본값을 int로 설정하면, 키가 없는 경우에는 0을 반환합니다.
char_count = defaultdict(int)
# 문자열의 각 문자를 순회합니다.
for char in s:
# 현재 문자의 출현 횟수를 1 증가시킵니다.
# 이 때, 해당 문자가 처음 나온 경우에는 기본값인 0에서 1을 더하게 됩니다.
char_count[char] += 1
# 각 문자와 그 출현 횟수를 출력합니다.
print(char_count)
위 코드는 입력 문자열 s의 각 문자를 순회하며, 해당 문자가 몇 번 나오는지 char_count라는 defaultdict에 저장합니다.
defaultdict는 키가 없는 경우에는 0을 기본값으로 반환하므로, 특정 문자가 처음 나올 때 KeyError를 발생시키지 않습니다.
코드를 실행하면, 각 문자와 그 출현 횟수를 출력합니다. 출력 결과는 다음과 같습니다.
defaultdict(<class 'int'>, {'H': 1, 'e': 1, 'l': 3, 'o': 2, ',': 1, ' ': 1, 'W': 1, 'r': 1, 'd': 1, '!': 1})
🔶문제 풀이 - 그리디 알고리즘을 이용한 풀이
import sys
from collections import defaultdict
# 참가자의 수를 입력받습니다.
n = int(input())
result = []
# 각 참가자의 정보를 입력받아 result 리스트에 저장합니다.
# 이 때, 튜플의 첫 번째 요소를 점수로 설정하여 나중에 점수를 기준으로 정렬할 수 있도록 합니다.
for _ in range(n):
x, y, z = map(int,input().split())
result.append((z,x,y)) # z: 점수, x: 학교 번호, y: 학생 번호
# result 리스트를 점수를 기준으로 내림차순 정렬합니다.
result.sort(reverse=True)
# defaultdict를 선언하여 각 학교의 수상자 수를 저장합니다.
winners=defaultdict(int)
# 답을 저장할 리스트를 선언합니다.
answer=[]
# 정렬된 result 리스트를 순회하면서,
for z,x,y in result:
# 같은 학교에서 두 명 이상 수상하지 않도록 합니다.
if winners[x]<2:
winners[x]+=1
# 수상자의 정보를 answer 리스트에 추가합니다.
answer.append((x,y))
# 상위 세 명을 찾았다면 반복을 종료합니다.
if len(answer)==3:
break
# 수상자의 학교 번호와 학생 번호를 출력합니다.
for i,j in answer:
print(i,j)
🔶문제 이해하기
아래와 같은 입력값이 주어졌다고 가정해 보겠습니다.
9
1 1 230
1 2 210
1 3 205
2 1 100
2 2 150
3 1 175
3 2 190
3 3 180
3 4 195
result 리스트를 점수를 기준으로 내림차순 정렬합니다.
[(230, 1, 1)
(210, 1, 2)
(205, 1, 3)
(195, 3, 4)
(190, 3, 2)
(180, 3, 3)
(175, 3, 1)
(150, 2, 2)
(100, 2, 1)]
1. winners 딕셔너리를 생성하여 각 학교의 수상자를 탐색합니다.
answer 리스트를 생성하여 수상자의 정보를 저장합니다.
2. 정렬된 result 리스트를 순회하면서, 같은 학교에서 두 명 이상 수상하지 않도록 합니다.
이를 위해 winners 딕셔너리를 사용하여 각 학교의 수상자 수를 체크합니다.
수상자의 정보를 answer 리스트에 추가합니다.
3. 상위 세 명을 찾으면 반복을 종료합니다.
answer 리스트의 길이가 3이 되면 반복을 종료하는 조건을 사용합니다.
4. 수상자의 학교 번호와 학생 번호를 출력합니다.
answer 리스트를 순회하면서 각 수상자의 정보를 출력합니다.
5. 최종적으로, 학교 1의 학생 1이 금메달 학생 2가 은메달 그리고 학교 3의 학생 4가 동메달을 수상하는 것을 알 수 있습니다.
'백준 알고리즘' 카테고리의 다른 글
백준 - 11725번 트리의 부모 찾기 python 문제풀이 [Hellfer] (2) | 2024.02.07 |
---|---|
백준 - 1238번 파티 python 문제풀이 [Hellfer] (2) | 2024.01.31 |
백준 - 1359번 복권 python 문제풀이 [Hellfer] (2) | 2024.01.29 |
백준 - 1268번 임시 반장 정하기 python 문제풀이 [Hellfer] (2) | 2024.01.27 |
백준 - 1543번 문서 검색 python 문제풀이 [Hellfer] (0) | 2024.01.19 |
백준 - 1817번 짐 챙시는 숌 python 문제풀이 [Hellfer] (0) | 2024.01.18 |
백준 - 14719번 빗물 python 문제풀이 [Hellfer] (0) | 2024.01.15 |
백준 - 14716번 현수막 python 문제풀이 [Hellfer] (2) | 2024.01.13 |