[백준] 2012번 등수 매기기

반응형
반응형

문제

2007년 KOI에 N명의 학생들이 참가하였다. 경시일 전날인 예비소집일에, 모든 학생들은 자신이 N명 중에서 몇 등을 할 것인지 예상 등수를 적어서 제출하도록 하였다.

KOI 담당조교로 참가한 김진영 조교는 실수로 모든 학생의 프로그램을 날려 버렸다. 1등부터 N등까지 동석차 없이 등수를 매겨야 하는 김 조교는, 어쩔 수 없이 각 사람이 제출한 예상 등수를 바탕으로 임의로 등수를 매기기로 했다.

자신의 등수를 A등으로 예상하였는데 실제 등수가 B등이 될 경우, 이 사람의 불만도는 A와 B의 차이 ( |A-B| )로 수치화할 수 있다. 당신은 N명의 사람들의 불만도의 총 합을 최소로 하면서, 학생들의 등수를 매기려고 한다.

각 사람의 예상 등수가 주어졌을 때, 김 조교를 도와 이러한 불만도의 합을 최소로 하는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 500,000) 둘째 줄부터 N개의 줄에 걸쳐 각 사람의 예상 등수가 순서대로 주어진다. 예상 등수는 500,000 이하의 자연수이다.

출력

첫째 줄에 불만도의 합을 최소로 할 때, 그 불만도를 출력한다.

 

이 문제를 푸니 그리디가 뭔지 감이 잡힌듯 싶다.(다른 분 코드를 참조 해서 풀었지만...ㅎㅎ)

 

그리디가 아니면 이렇게 풀리가 없는데... 그리디니까...

package _2020_06_10.D;

import java.util.Arrays;
import java.util.Scanner;

public class Main {

	static int arr[];
	public static void main(String[] args) {
	  Scanner sc = new Scanner(System.in);	
	  int n = sc.nextInt();
	  
	  arr = new int[n];
	  for(int i = 0; i<n;i++) {
		  arr[i] = sc.nextInt();
	  }
	  
	  Arrays.sort(arr);
	  
	  long sum = 0;
	  for(int i = 1;i<=n;i++) {
		  sum += Math.abs(arr[i-1] - i);
	  }
	  
	  System.out.println(sum);
		
		

	}

}

 

여기서 그리디가 적용된 부분은

sum += 쪽이 그리디가 적용되었다.

 

생각해보면 1 부터 n까지 등수가 전부 다를 수 있고.. 동률도 있을 수 있고... 또.... 음... 굉장히 많다.

하지만 그리디로 적용하면 위같은 문제는 해결된다.

뭐 동률같은건 동석차 없이 라고 문제에서 명시 되었기 때문에 동률은 될리가 없다.

만약 된다면 그때 부터는 그리디 문제가 아니겠지...ㅎㅎ

 

아무튼...

이게 왜 가능하면 예상등수와 실제 등수를 뺏을때 최소가 되는 경우는

1등과 꼴지는 무조건적으로 결정하고 시작하는 방법이다.

왜냐하면 이 둘은 굉장히 편차가 크기 때문에 미리 제거 하는게 좋다고 생각한다.

 

하지만 두개만 생각하다보면 문제가 꼬일 수 있다.

 

그냥 오름 차순으로 정렬해보면 답이 쉽게 나온다.

오름 차순으로 정렬해보면 최소한의 경우가 나온다.

이게 무슨 말이냐면

1등 2등 3등 4등 5등 이 있다고 가정하면...

예상 등수가 이 밑에 들어간다.(물론 코드에는 예상 등수가 밑에 들어가지는 않는다.)

 

어차피 1등과 5등은 이미 정해졌기 때문에 논외로 생각하고...

 

이미 정렬되었기 때문에 최솟값을 구할 수 있다. 아까랑 챗바퀴 도는것 같은데...

아무튼 정렬하면 된다.... 

 

즉... 정렬 => 실제 등수..

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

    public static void main(String[] args) throws IOException {

        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        int count = Integer.parseInt(bf.readLine());

        PriorityQueue<Integer> qu = new PriorityQueue<>();

        for(int i=0; i<count; i++) {
            int input = Integer.parseInt(bf.readLine());
            qu.add(input);
        }

        long angry = 0L;

        while (!qu.isEmpty()) {
            for(int i=1; i<=count; i++) {
                int poll = qu.poll();
                if(i < poll) {
                    angry = angry + (poll - i);
                } else {
                    angry = angry + (i - poll);
                }
            }
        }
        
        System.out.print(angry);

    }
}

반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 2503번 숫자 야구  (0) 2020.06.12
[백준] 1202번 보석 도둑  (0) 2020.06.11
[백준] 2812번 크게 만들기  (0) 2020.06.10
[백준] 5545번 최고의 피자  (0) 2020.06.09
[백준] 3184번 양  (0) 2020.06.09

댓글

Designed by JB FACTORY