본문 바로가기
알고리즘/백준

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

by Renechoi 2023. 6. 24.

백준 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());
		}

	}

}

 

 

 

 

 

 

 

반응형