코딩테스트/BOJ

[BOJ] 1206 사람의 수 - JAVA

5월._. 2022. 6. 17.
728x90

1. 문제

 

1206번: 사람의 수

첫째 줄에 N이 주어진다. 둘째 줄부터 N개의 줄에 각 문항의 평균 점수가 주어진다. N은 50보다 작거나 같은 자연수이고, 평균 점수는 0보다 크거나 같고, 10보다 작거나 같은 소수이다. 항상 소수

www.acmicpc.net

송유진은 길거리에서 사람들에게 설문조사를 하고 있다. 설문조사에는 N개의 문항이 있고, 설문에 응한 사람은 각 문항을 0보다 크거나 같고, 10보다 작거나 같은 정수로 대답해야 한다.
설문조사를 모두 마친 후 유진이는 각 문항의 평균 점수 소수점 셋째 자리에서 자른 값을 보고서 종이에 적고 사무실로 돌아왔다. 예를 들어, 어떤 문항에 각 사람이 점수를 4, 6, 10점으로 대답했다면, 평균 점수는 6.666이다. 이제 설문조사 결과를 보고해야 하는데, 문제가 하나 생겼다. 평균 점수만 알고 있기 때문에, 설문조사에 참여한 사람의 수를 알 수 없다는 점이다.
각 문항의 평균 점수가 주어진다. 이때 설문조사에 참여한 사람의 수를 구해보자.


2. 풀이

double 풀이

1.  입력값에서 소수점 부분만 남긴다. (주석 단 코드처럼 하면 부동소수점 오차때문에 틀린다.)

2.  num=사람 수다. 명수를 올려가면서 탐색한다.

2-1.  cases에 점수를 사람 수로 나눈 값을 저장한다. 점수의 범위는 1점부터 사람 수까지로 한다. 입력값을 소수점부분만 받았기 때문에 그 이상은 의미가 없기 때문이다.

2-2.  N개의 입력값을 하나하나 binarySearch로 찾는다. 이 때, 나는 cases 배열을 1001칸으로 고정했으므로 범위를 지정해야 한다. 0부터 num+1까지로 한다. fromIdx는 포함, toIdx는 제외라서 num+1이어야 한다.

2-3.  만약 입력값이 cases에 없다면 flag를 false로 변경하고 반복문을 중단한다.

2-4.  반복문이 끝난 뒤에도 flag가 true라면 정답을 찾은 것이므로 num(사람수)를 출력하고 끝낸다.

import java.io.*;
import java.util.*;

public class BOJ_1206_사람의수 {
   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      int N = Integer.parseInt(in.readLine());
      double[] avg = new double[N];

      for (int i = 0; i < N; i++) {
//       avg[i] = 0.001 * Integer.parseInt(in.readLine().split("\\.")[1]);
         avg[i] = Double.parseDouble(in.readLine());
         avg[i] = avg[i] - Math.floor(avg[i]);
         avg[i] = Math.round(avg[i]*1000.0)/1000.0;
      }


      boolean flag;
      double[] cases = new double[1001];
      for (int num = 1; num <= 1000; num++) {
         for(int score=1;score<=num;score++){
            cases[score] = Math.floor(((double)score/num)*1000)/1000.0;
         }
         flag = true;
         for(int j=0;j<N;j++){
            if(Arrays.binarySearch(cases, 0, num+1, avg[j]) <0){
               flag = false;
               break;
            }
         }
         if(flag){
            System.out.println(num);
            return;
         }
      }
   }

}

 

BigDecimal 풀이

부동소수점때문에 너무 힘들어서 BigDecimal 타입을 써봤다.

1.  입력값을 .으로 구분한 뒤 [1]칸값 앞에 "0."을 붙인다. 이걸 BigDecimal로 만든다.

2.  방식은 위와 흡사하다. 하지만 나누기를 할 때(19번째 줄) 3번째 자리까지, 그 외의 자리는 버린다(RoundingMode.DOWN) 고 설정한 점이 다르다.

3.  double 풀이에서는 점수가 0일때 어차피 항상 0이라서 굳이 계산하지 않고 score를 1부터 시작했는데, BigDecimal은 객체이므로 꼭 계산해줘야 한다.

import java.io.*;
import java.math.*;
import java.util.*;

public class BOJ_1206_사람의수2 {
   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      int N = Integer.parseInt(in.readLine());
      BigDecimal[] avg = new BigDecimal[N];

      for (int i = 0; i < N; i++) {
         avg[i] = new BigDecimal("0."+in.readLine().split("\\.")[1]);
      }

      boolean flag;
      BigDecimal[] cases = new BigDecimal[1001];
      for (int num = 1; num <= 1000; num++) {
         for(int score=0;score<=num;score++){
            cases[score] = BigDecimal.valueOf(score).divide(BigDecimal.valueOf(num),3, RoundingMode.DOWN);
         }
         flag = true;
         for(int j=0;j<N;j++){
            if(Arrays.binarySearch(cases, 0, num+1, avg[j]) <0){
               flag = false;
               break;
            }
         }
         if(flag){
            System.out.println(num);
            return;
         }
      }

   }

}

3. 결과

소수점때문에 너무너무너무 힘들었다..

맨 위의 코드는 BigDecimal을 이용한 코드다. 메모리도 시간도 훨씬 더 많이 걸린다. 새 객체를 계속 생성해서 그런 것 같다.

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 1057 토너먼트 - JAVA  (0) 2022.06.20
[BOJ] 1246 온라인 판매 - JAVA  (0) 2022.06.19
[BOJ] 1183 약속 - JAVA  (0) 2022.06.16
[BOJ] 1198 삼각형으로 자르기 - JAVA  (0) 2022.06.15
[BOJ] 1205 등수 구하기 - JAVA  (0) 2022.06.14

댓글