무지개곰
article thumbnail
반응형

문제

https://www.acmicpc.net/problem/1206

입력

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

출력

첫째 줄에 설문조사에 참여한 사람의 수를 출력한다. 만약, 가능한 정답이 여러 가지라면, 가장 작은 값을 출력한다.


문제 풀이

문제 해석 및 계획

설문에 참여한 '사람의 수는 최소 1명이고 최대 1000명'이 될 수 있다고 생각하였습니다.

'평균은 설문 결과의 총합 / 사람 수'이고 문제에서는 소수 셋째 자리까지만 표기하기에 1000을 곱하여 소수를 정수로 바꾸어 몫을 통하여 비교를 하려고 생각하였습니다.

그렇게 되면 '설문 결과의 총합은 1000의 배수'가 될 것이고 '평균* 사람 수 보다 크거나 같은 가장 작은 1000의 배수'를 평균을 위하여 사람 수로 나누어 비교를 하기로 계획하였습니다.

오답 노트

로직은 실수 없이 작성하였지만 결과는 틀렸습니다. 소수 간의 계산은 부동소수점으로 인하여 차이가 발생한다는 것을 알기에 1000을 곱하여 정수화하여 계산을 하였기에 원인을 못 찾았습니다.

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main(){
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)

	defer writer.Flush()

	var N int
	fmt.Fscan(reader, &N)

	averages := make([]int,N)
	for i:=0 ; i<N ; i++ {
		var input float64
		fmt.Fscan(reader, &input)
		averages[i] = int(input*1000)
	}

	for i:=1 ; i<=1000 ; i++ {
		check := true
		for j:=0 ; j<N ; j++ {
			PossibleMinAvarage := averages[j] * i
			originTotal := 0
			if PossibleMinAvarage % 1000 != 0 {
				originTotal = (PossibleMinAvarage/1000 + 1)*1000
			}else {
				originTotal = PossibleMinAvarage
			}
				
			if originTotal/i != averages[j] {
				check = false
				break
			}
		}
		if check {
			fmt.Fprintf(writer, "%.3f", float64(i))
			break
		}
	}
}

정답

혹시나 하는 마음에 입력을 문자열로 받아 소수점을 지우고 숫자로 변환하였고 결과는 맞았습니다.

1000을 곱하여 정수가 되었기에 문제가 없을 것이라고 생각하였지만 문제점이 있는 것 같습니다.

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main(){
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)

	defer writer.Flush()

	var N int
	fmt.Fscan(reader, &N)

	averages := make([]int,N)
	for i := 0; i < N; i++ {
		var input string
		fmt.Fscan(reader, &input)
		input = strings.ReplaceAll(input, ".","")
		average, _ := strconv.Atoi(input)
		averages[i] = average
	}

	for i:=1 ; i<=1000 ; i++ {
		check := true
		for j:=0 ; j<N ; j++ {
			PossibleMinAvarage := averages[j] * i
			originTotal := 0
			if PossibleMinAvarage % 1000 != 0 {
				originTotal = (PossibleMinAvarage/1000 + 1)*1000
			}else {
				originTotal = PossibleMinAvarage
			}
				
			if originTotal/i != averages[j] {
				check = false
				break
			}
		}
		if check {
			fmt.Fprint(writer, i)
			break
		}
	}
}

느낀 점

부동소수점을 완벽히 알지 못하고 소수끼리의 연산에는 오류가 난다는 것만 알고 있었기에 시간이 오래 걸렸던 문제였습니다. 아직까지 브론즈 문제부터 실버문제까지만 다루고 있지만 항상 느끼는 점은 새로운 언어를 시작할 때는 난이도가 높은 문제를 통하여 로직을 생각하는 문제보다 기본 문제들을 통하여 부족한 개념들을 채우는 것이 우선시 되어야겠다고 느꼈습니다. 한 걸음씩 나아가며 원하는 수준을 달성하기 위하여 힘내겠습니다.

반응형
profile

무지개곰

@무지개곰

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!