백준 4796번
문제
등산가 김강산은 가족들과 함께 캠핑을 떠났다. 하지만, 캠핑장에는 다음과 같은 경고문이 쓰여 있었다.
캠핑장은 연속하는 20일 중 10일동안만 사용할 수 있습니다.
강산이는 이제 막 28일 휴가를 시작했다. 이번 휴가 기간 동안 강산이는 캠핑장을 며칠동안 사용할 수 있을까?
강산이는 조금 더 일반화해서 문제를 풀려고 한다.
캠핑장을 연속하는 P일 중, L일동안만 사용할 수 있다. 강산이는 이제 막 V일짜리 휴가를 시작했다. 강산이가 캠핑장을 최대 며칠동안 사용할 수 있을까? (1 < L < P < V)
입력
입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, L, P, V를 순서대로 포함하고 있다. 모든 입력 정수는 int범위이다. 마지막 줄에는 0이 3개 주어진다.
출력
각 테스트 케이스에 대해서, 강산이가 캠핑장을 최대 며칠동안 사용할 수 있는지 예제 출력처럼 출력한다.
예제 입력
5 8 20
5 8 17
0 0 0
예제 출력
Case 1: 14
Case 2: 11
풀이 과정
연속하는 20일 중 10일동안만 사용할 수 있다. 28일 휴가를 시작한다면?
- 28일동안 겹치지 않는 20일은 한 번만 포함될 수 있으므로 10 * 1일은 캠핑장을 온전히 이용할 수 있다.
- 남은 8일은 캠핑장을 이용할 수 있는 10일보다 작으므로 온전히 8일을 이용할 수 있다.
이와 같은 방법으로 공식을 작성해보면 다음과 같다.
최대 사용가능일 = (V // P) * L + (V % P)
이를 파이썬으로 표현해보자.
i = 1
while True:
L, P, V = map(int, input().split())
if L == 0 :
break
else:
result = (V // P) * L + (V % P)
print(f'Case {i}: {result}')
i += 1
F string 을 사용해서 무한반복으로 출력하다가 0이 들어오는순간 break로 반복을 종료시키는 로직이다.
제출하니 틀렸다고 한다. 뭔가를 놓친건가 싶지만 몇번 테스트를 돌려도 예외가 발생하는 곳을 알아내기가 힘들었다.
(추후에 테스트해보다가 이것과는 상관없다는 것을 알게 되었다.)
수정해보자.
cases = []
while True:
case = list(map(int, input().split()))
if case[0] == 0:
break
cases.append(case)
i = 1
for case in cases:
L, P, V = case[0], case[1], case[2]
result = (V // P) * L + (V % P)
print(f'Case {i}: {result}')
i += 1
- cases 라는 배열을 생성해놓고 들어오는 입력값을 배열로 변환 후 차례로 집어넣는다.
- 만약 1번째 인자로 0이 들어오면 무한루프를 종료하고,
- cases에서 case로 하나씩 꺼내면서 첫 공식을 실행한다.
결과는... 또 틀렸다.
테스트 코드를 추가해보던 중 3 6 70 을 집어넣었을 때 빼먹은 걸 발견할 수 있었다. 70 / 6 의 나머지는 4인데 연속으로 사용할 수 있는 날은 3일이므로 4가 아니라 더 작은 3이 결과에 더해져야하는 것이 맞다.
간단하게 작성해서 코드에 추가하고 제출해보니 정답이 나왔다.
cases = []
while True:
case = list(map(int, input().split()))
if case[0] == 0:
break
cases.append(case)
i = 1
for case in cases:
L, P, V = case[0], case[1], case[2]
if V % P > L :
rest = L
else :
rest = V % P
result = (V // P) * L + rest
print(f'Case {i}: {result}')
i += 1
최종답안
최대 사용가능일 = (V // P) * L + min((V % P), L)
i = 1
while True:
L, P, V = map(int, input().split())
if L == 0 :
break
else:
rest = min(V % P, L)
result = (V // P) * L + rest
print(f'Case {i}: {result}')
i += 1
- 문제의 조건 중 L은 무조건 1보다 크다는 조건이 있으므로 0 이 들어오는 순간 마지막 테스트케이스라는 것을 알 수 있다. 굳이 L,P,V의 합이 0 같은 방식이 아니여도 값 하나만 가지고 알 수 있다.
- min함수는 인자 중 작은 값을 리턴해준다. 크기를 비교하는 값들 중 하나가 결과적으로 반환된다면 min이나 max로 때에 따라 쓸 수 있다.
- f string 표기법은 JS의 템플릿 리터럴과 유사하게 파이썬을 표기할 수 있게 해줘서 개인적으로는 %를 사용하는 방법보다 가독성이 좋다고 느껴져서 더 선호한다.