The+Trip

= PC/UVa ID: 110103/10137 - 여행(The Trip) = 일 년에 한 번씩 다른 여행지로 여행을 가는 학생 모임이 있다. 그 학생들은 지금까지 인디애나폴리스, 피닉스, 내시빌, 필라델피아, 산호세, 아틀란타를 여행했다. 이번 봄에는 아인트호벤으로 여행을 갈 계획이다.

이 학생들은 여행 경비를 모두 똑같이 부담하기로 합의했지만 돈을 쓸 때마다 나눠서 내는 것은 별로 실용적이지 못하다. 그래서 한 명씩 식비, 호텔비, 택시비, 비행기표를 부담하기로 한다. 여행이 끝난 후에 각 학생이 지출한 내역을 계산한 다음 1센트 단위 내에서 모든 학생들이 쓴 돈이 같도록 돈을 주고 받는다. 하지만 이전 여행의 경험에 비추어보면 돈을 주고 받는 과정은 정말 지루하고 오랜 시간을 요하는 작업이었다. 지출 내역이 주어졌을 때 모든 학생이 쓴 돈이 (1센트 단위 내에서) 똑같아지기 위해 전달되어야 하는 최소 액수를 구해보자.

입력
표준 입력을 통해 여러 번의 여행에 대한 정보가 저장된다. 각 여행은 여행에 참가한 학생 수를 나타내는 정수 n으로 구성된다. 이 정수 밑으로는 n개의 줄이 입력되는데, 각 줄에는 달러와 센트 단위로 각 학생이 지출한 경비가 입력된다. 학생 수는 1000명을 넘지 않으며 어떤 학생도 $10,000.00 이상 지출하지 않는다. 마지막 여행에 대한 정보 다음 줄에는 0만 들어있는 줄이 입력된다.

출력
각 여행에 대해 각 학생이 사용한 금액이 똑같아지기 위해 전달되어야 하는 금액의 총합을 출력한다.

입력 예
3 10.00 20.00 30.00 4 15.00 15.01 3.00 3.01 0

출력 예
$10.00 $11.99

출처
[]

Source Code code format="java5"

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

public class TheTrip { public static void main(String[] args) { Scanner scan = new Scanner(System.in);

while(true) { int n = scan.nextInt;// 여행에 참가한 학생 수

// 0을 받으면 종료한다. if(n == 0) { return; }

double[] m = new double[n];// 지출 내역 for(int i = 0; i < n; i++) { m[i] = scan.nextDouble; }

process(m, n); }   }

public static void process(double[] m, int n) { // 센트 단위로 저장한다. Integer[] c = new Integer[n]; for(int i = 0; i < n; i++) { c[i] = (int) (m[i] * 100); }

// 내림차순으로 정렬한다. Arrays.sort(c, Collections.reverseOrder);

// 평균과 나머지를 구한다. int sum = 0; for(int i = 0; i < n; i++) { sum += c[i]; }   int avg = sum / n;    int rem = sum % n;

// 전달되어야 하는 금액의 총합을 구한다. sum = 0; for(int i = 0; i < n; i++) { if(c[i] > avg) { if(i < rem) { sum += c[i] - (avg + 1); }   else { sum += c[i] - avg; }   }    }    System.out.println((double)sum / 100); }   }

code

Comment 어려운 문제였다. 다시한번 문제를 정말 꼼꼼히 읽어봐야 한다는 것을 느꼈다. 키 포인트는 지출 비용을 완전 똑같이 만드는 것이 아니라는 것이다. 생각해보면 모두가 똑같을 수가 없다. 센트 단위라는 것도 중요하다. 부동소수점은 돈 계산시에는 고정소수점으로 변환후 계산해야한다. 이 문제를 풀면서 우연하게 자바에서 배열을 내림차순으로 쉽게 정렬하는 방법을 알게되었다.