Computer Science/알고리즘

백준 Java | BOJ #1713 후보 추천하기

토마토. 2023. 1. 31. 10:50
package P1713;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Array;
import java.util.*;

public class Main {
    static int N;
    static int total_count;
    static int[] recommended;
    static ArrayList<Candidate> candidate_list;
    static ArrayList<Candidate> photo;

    public static void main(String[] args) throws FileNotFoundException {
        System.setIn(new FileInputStream("src/P1713/input.txt"));
        Scanner scanner = new Scanner(System.in);
        N = scanner.nextInt(); // 사진틀의 개수
        total_count = scanner.nextInt();
        photo = new ArrayList<>(); // size 최대 N
        candidate_list = new ArrayList<>();
        recommended = new int[total_count];
        for (int i=0;i<total_count;i++){
            recommended[i] = scanner.nextInt();
        }
        process();
        Collections.sort(photo, new Comparator<Candidate>() {
            @Override
            public int compare(Candidate o1, Candidate o2) {
                return o1.id - o2.id;
            }
        });
        for (Candidate candidate : photo){
            System.out.print(candidate.id + " ");
        }
        System.out.println();
    }
    public static boolean candidate_list_contains(int id){
        for (Candidate candidate : candidate_list){
            if (candidate.id == id){
                return true;
            }
        }
        return false;

    }
    public static Candidate get_candidate(int id){
        for (Candidate candidate : candidate_list){
            if (candidate.id == id){
                return candidate;
            }
        }
        return null;
    }
    public static void process(){
        for (int i=0;i<total_count;i++) {
            // 특정 학생을 추천하면, 반드시 사진틀에 게시되어야 한다
            int current = recommended[i];
            Candidate candidate;
            if (candidate_list_contains(current)){
                candidate = get_candidate(current);
            } else {
                candidate = new Candidate(current);
                candidate_list.add(candidate);
            }
            if (candidate.has_photo) {
                // 사진이 이미 등록되어 있으면 count ++
                candidate.vote_count++;
            } else {
                if (photo.size() >= N) {
                    // 사진틀에 게시된 사진이 삭제되는 경우에는 해당 학생이 추천받은 횟수는 0으로 바뀐다.
                    Collections.sort(photo);
                    Candidate remove_candidate = photo.get(0);
                    remove_candidate.time_stamp = 0;
                    remove_candidate.vote_count = 0;
                    remove_candidate.has_photo = false;
                    photo.remove(0);
                }
                // 그 자리에 새롭게 추천받은 학생의 사진을 게시한다.
                photo.add(candidate);
                candidate.vote_count++;
                candidate.has_photo = true;
                candidate.time_stamp = i;
            }
        }
    }
}
class Candidate implements Comparable<Candidate>{
    public int id;
    public int vote_count;
    public int time_stamp;
    public boolean has_photo;
    Candidate(int id){
        this.id = id;
        vote_count = 0;
        time_stamp = 0;
        has_photo = false;
    }

    @Override
    public int compareTo(Candidate o2) {
        // 가장 적은 학생이 index 0에 오도록 오름차순 정렬
        // 사진틀 빈 게 없으면 현재까지 추천 받은 횟수가 가장 적은 학생의 사진을 삭제하고,
        // 이때, 현재까지 추천 받은 횟수가 가장 적은 학생이 두 명 이상일 경우에는
        // 그러한 학생들 중 게시된 지 가장 오래된 사진을 삭제한다.
        int compare_vote_count = this.vote_count - o2.vote_count;
        if (compare_vote_count == 0){
            return this.time_stamp - o2.time_stamp;
        } else {
            return compare_vote_count;
        }
    }

    @Override
    public String toString(){
        return "(" + id + ": " + vote_count + ")";
    }
}