백준(boj) 1476 파이썬(python)

oneao·2022년 8월 30일
0

백준 BOJ

목록 보기
4/4

문제

백준 1476번으로 가려면 여기를 클릭하면 된다.

정답 코드

E, S, M = input().split()
E = int(E)
S = int(S)
M = int(M)

a = 0
b = 0
c = 0
err = 0
while True:
    while (b * 28 + S) >= (c * 19 + M):
        while (c * 19 + M) >= (a * 15 + E):
            if (b * 28 + S) == (c * 19 + M) == (a * 15 + E):
                print(f"{a * 15 + E}")
                err += 1
                break
            else:
                a += 1
        if err > 0:
            break
        c += 1
    if err > 0:
        break
    b += 1

풀이

대충 어떻게 풀면 될지 감은 오는데, 정확한 풀이를 쓰기까지 시간이 조금 걸렸던 문제였다.
처음에는 최소공배수를 구하면 되는 것이라고 생각했다가, 그게 아니라는 것을 깨달았다.
그냥 연립방정식을 푸는 식으로 해결하면 된다는 아이디어를 생각해냈다.

그런데, 코딩으로 연립방정식을 푸는 방법은 변수에 숫자를 넣어가며 bruteforce를 하는 방법밖에 없었기 때문에 bruteforce로 구현하는 데 조금 시간이 걸렸다.

연립방정식은 다음과 같았다.
구해야하는 연도를 N으로 놓고
주어진 숫자들을 E, S, M이라고 했을 때,

N = 15 a + E = 28 b + S = 19 * c + M

이 되는 a, b, c를 찾으면 풀리는 문제였다.

맞닥뜨렸던 문제1

어떻게 반복문을 중첩해야 가장 효율적인 코드를 짤 수 있을까?

해결

다른 조건이 똑같을 때 가장 큰 숫자가 되는 수를 가장 먼저 while문에 넣으면 된다.
스포츠경기를 할 때 점수판이 있다고 해보자
눈앞에
1~15인 점수판, 1~28인 점수판, 1~19인 점수판 이 순서대로 있다고 생각해보자.
시작은 1 | 1 | 1 의 상태일 것이다.

a, b, c는 각각 이 점수판이 몇 번을 끝까지 돌아갔는지를 말해주는 숫자이다.
E, S, M은 그러고 남은 숫자인 것이다.

만약 N이 100이라고 해보자.
세 개의 점수판이 열심히 돌아갈 것이다.
그렇게 각 점수판을 100점에 맞춰 돌리면,

점수판은 현재
10 | 16 | 5
의 상태일 것이다.

1) 1부터 15까지 밖에 없는 점수판은 6번을 끝까지 돌리고, 10점이 남은 것이다.
100 = 15 * 6 + 10

2) 1부터 28까지 밖에 없는 점수판은 3번을 끝까지 돌리고, 16점이 남은 것이다.
100 = 28 * 3 + 16

3) 1부터 19까지 밖에 없는 점수판은 5번을 끝까지 돌리고, 5점이 남은 것이다.
100 = 19 * 5 + 5

더 많은 숫자까지 표시할 수 있는 점수판일 수록 끝까지 돌아간 횟수가 적을 수밖에 없다.
점수판이 돌아간 횟수는
28까지 있는 점수판 < 19까지 있는 점수판 < 15까지 있는 점수판
일 수밖에 없는 것이다.

이 순서대로 숫자가 늦게 올라가도록 짜면 되는 것이다.

맞닥뜨렸던 문제2

세 개의 숫자 중 가장 작은 수부터 늘려가면서 반복문을 계속 돌리면 되는데, 이를 코딩으로 구현하기까지 시간이 조금 걸렸다.

해결

어떤 조건에 a를 그만 늘리고 c를 늘려야 하는지를 계속 생각했다.
어떤 조건이 됐을 때 c를 그만늘리고 b를 늘려야하는지.

해답을 찾은 것이 바로 이 코드이다.
멈추는 부분은 빼고 이부분의 해답부분만을 가져왔다.

while True:
    while (b * 28 + S) >= (c * 19 + M):
        while (c * 19 + M) >= (a * 15 + E):
            if (b * 28 + S) == (c * 19 + M) == (a * 15 + E):
                print(f"{a * 15 + E}")
            else:
                a += 1
        c += 1
    b += 1

c를 늘려가다가 같은 조건에서 더 큰 수일 b 28 + S를 c 19 + M 가 뛰어넘으면, b를 늘릴 차례인 것이다. 같은 원리로 그 안에서 a를 늘려가다가 같은 조건에서 더 큰 수일 c 19 + M를 a 15 + E 가 뛰어넘으면, c를 늘릴 차례인 것이다.

후기

아무것도 찾아보지 않고 계속해서 생각해내어 한 번에 해결한 것이 너무나도 뿌듯했다.
그림을 그려가며 설명하면 더 좋았을 텐데, 텍스트로만 풀어써야돼서 너무 장황하게 설명하게 된 것이 아쉽다. 유튜브 동영상이라도 올리고 싶은 심정. 어쨌든, 풀었다. 이해가안 가는 부분이 있으면 댓글 달아주길! 바로 설명해드리겠다!

0개의 댓글