백준 2817 ALPS식 투표 (JAVA 자바 풀이)

전혀 어렵게 풀 문제가 아니었는데 문제를 잘못 읽어서 한참을 헤맸다.
제대로 안 읽은 부분을 밑줄 쳐보면 다음과 같다.

1) 전체 대회 참가자의 5% 미만을 걸러야 하는 조건
참가자가 투표를 하지 않을 수도 있다는 것만 보고 총 투표수를 받아야 되나 생각했다. 어떻게 할까를 고민하다가 그냥 한 번에 받는 방법이 제일 간단해 보여서 이렇게 짰었다.
List<Staff> staffs = new ArrayList<>();
		List<Double> scores = new ArrayList<>();
		Map<String, Integer> staffInformation = new LinkedHashMap<>();
		while (staffCounts--> 0) {
			StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());
			String name = stringTokenizer.nextToken();
			int votes = Integer.parseInt(stringTokenizer.nextToken());
			staffInformation.put(name, votes);
		}
		for (Map.Entry<String, Integer> stringIntegerEntry : staffInformation.entrySet()) {
			String name = stringIntegerEntry.getKey();
			Integer votes = stringIntegerEntry.getValue();
			if(votes < participants * 0.05){
				continue;
			}
			Staff staff = Staff.of(name, votes);
			staffs.add(staff);
			scores.addAll(staff.getScores());
		}
먼저 입력값을 다 받아놓고 총 투표수를 계산한 다음 그거로 5% 미만 값을 필터링 하는 방식이다.
계속 틀려서 알고 봤더니 총 투표한 수의 5%가 아니라 전체 참가자 수의 5%이다.
즉, 다음과 같이 맨 처음 받은 staffCounts만으로도 충분했던 것이다.
int participants = Integer.parseInt(bufferedReader.readLine());
int staffCounts = Integer.parseInt(bufferedReader.readLine());
예제 입력 3번 케이스의 경우 총 참가자 수는 206278인데 투표수는 177925이다. 이처럼 다르게 값이 주어지는 경우가 있기 때문에 값을 잘못 계산하면 통과하지 못하는 테스트들이 생긴다.
206278
5
D 44687
A 68188
C 7008
B 48377
G 9665
2) 점수는 실수로 계산되어야 한다는 것
1부터 14까지 나누어 계산되는 값이 정수가 아니라 실수였다. 정수로 계산하면 겹치는 경우가 생긴다. 이 경우 다음과 같은 코드에서 여러 개를 고르게 되기 때문에 문제가 생긴다.
for (int i = 0; i < 14; i++) {
   Double score = scores.get(i);
   staffs.stream().filter(staff -> staff.isOwn(score))
      .forEach(Staff::receiveChip);
}
public boolean isOwn(Double thatScore) {
   return scores.stream().anyMatch(score -> score.equals(thatScore));
}
3) 5% 이상의 투표수를 받은 경우 칩이 0이라도 출력해야 한다.

문제 조건에서 5% 이상인 스태프에 대해 칩의 개수를 출력하라고 했기 때문에 전부 출력해주어야 한다.
예를 들어 다음과 같은 테스트 셋의 경우
100
6
A 20
B 19
C 18
D 17
E 16
F 5

이렇게 답이 나와야 한다.
괜히 0을 출력 안하려고
staffs.stream().filter(staff -> staff.getChipCounts() !=0).forEach(System.out::println);
이렇게 필터 조건을 걸어서 또 틀렸다. 다음과 같이 그냥 출력하면 된다.
staffs.forEach(System.out::println);
💡 코드 구현
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
	private static final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
	public static void main(String[] args) throws IOException {
		int participants = Integer.parseInt(bufferedReader.readLine());
		int staffCounts = Integer.parseInt(bufferedReader.readLine());
		List<Staff> staffs = new ArrayList<>();
		List<Double> scores = new ArrayList<>();
		while (staffCounts-- > 0) {
			StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());
			String name = stringTokenizer.nextToken();
			int votes = Integer.parseInt(stringTokenizer.nextToken());
			if (votes < participants * 0.05) {
				continue;
			}
			Staff staff = Staff.of(name, votes);
			staffs.add(staff);
			scores.addAll(staff.getScores());
		}
		staffs.sort(Staff::compareTo);
		scores.sort(Comparator.comparingDouble(Double::doubleValue).reversed());
		for (int i = 0; i < 14; i++) {
			Double score = scores.get(i);
			staffs.stream().filter(staff -> staff.isOwn(score))
				.forEach(Staff::receiveChip);
		}
		staffs.forEach(System.out::println);
	}
	static class Staff implements Comparable<Staff> {
		private String name;
		private int votes;
		private List<Double> scores;
		private int chipCounts;
		public Staff(String name, int votes, List<Double> scores) {
			this.name = name;
			this.votes = votes;
			this.scores = scores;
		}
		public static Staff of(String name, int votes) {
			List<Double> list = new ArrayList<>();
			for (int i = 1; i <= 14; i++) {
				list.add((double)votes / i);
			}
			return new Staff(name, votes, list);
		}
		public boolean isOwn(Double thatScore) {
			return scores.stream().anyMatch(score -> score.equals(thatScore));
		}
		public List<Double> getScores() {
			return scores;
		}
		@Override
		public String toString() {
			return name + " " + chipCounts;
		}
		public void receiveChip() {
			chipCounts++;
		}
		public String getName() {
			return name;
		}
		@Override
		public int compareTo(Staff that) {
			return this.name.compareTo(that.getName());
		}
	}
}
'알고리즘 > 백준' 카테고리의 다른 글
| 백준 7785 회사에 있는 사람 (JAVA 자바 풀이) (0) | 2023.06.25 | 
|---|---|
| 백준 1181 단어 정렬 (JAVA 자바 풀이) | 문자열 길이순, 알파벳 순 정렬, 스트링 compareTo 메서드, thenComparing 메서드 (0) | 2023.06.25 | 
| 백준 2840 행운의 바퀴 (JAVA 자바 풀이) (0) | 2023.06.24 | 
| 백준 1730 판화 (JAVA 자바 풀이) (0) | 2023.06.09 | 
| 백준 11068 회문인 수 (JAVA 자바 풀이) (1) | 2023.06.09 |