목차
손익분기점(#1712)
- Problem
월드전자는 노트북을 제조하고 판매하는 회사이다. 노트북 판매 대수에 상관없이 매년 임대료, 재산세, 보험료, 급여 등 A만원의 고정 비용이 들며, 한 대의 노트북을 생산하는 데에는 재료비와 인건비 등 총 B만원의 가변 비용이 든다고 한다. 예를 들어 A=1,000, B=70이라고 하자. 이 경우 노트북을 한 대 생산하는 데는 총 1,070만원이 들며, 열 대 생산하는 데는 총 1,700만원이 든다. 노트북 가격이 C만원으로 책정되었다고 한다. 일반적으로 생산 대수를 늘려 가다 보면 어느 순간 총 수입(판매비용)이 총 비용(=고정비용+가변비용)보다 많아지게 된다. 최초로 총 수입이 총 비용보다 많아져 이익이 발생하는 지점을 손익분기점(BREAK-EVEN POINT)이라고 한다. A, B, C가 주어졌을 때, 손익분기점을 구하는 프로그램을 작성하시오.
- Hint
미지수로 된 식을 먼저 생각해보고 쓸모없는 식을 trim 한다.
컴퓨터에서는 0으로 나누지 못하는 것을 생각한다
- Solution
조건문을 이용한 풀이
a,b,c=map(int,input().split())
if c-b<=0:
print('-1')
else:
print(f'{int(a/(c-b)+1)}')
문제에서는 손익분기에 다다르지 못할때 -1을 프린트 하라고 했다. c-b가 0인 경우는 계산상 오류이고 이 또한 손익분기에 접근하지 못하기 때문에 하나의 조건문에 같이 삽입하였고 그렇지 않는 경우에는 몫을 구하는 식을 이용하여 손익분기의 기준을 구했다.
벌집(#2292)
- Problem
위의 그림과 같이 육각형으로 이루어진 벌집이 있다. 그림에서 보는 바와 같이 중앙의 방 1부터 시작해서 이웃하는 방에 돌아가면서 1씩 증가하는 번호를 주소로 매길 수 있다. 숫자 N이 주어졌을 때, 벌집의 중앙 1에서 N번 방까지 최소 개수의 방을 지나서 갈 때 몇 개의 방을 지나가는지(시작과 끝을 포함하여)를 계산하는 프로그램을 작성하시오. 예를 들면, 13까지는 3개, 58까지는 5개를 지난다.
- Hint
칸수가 늘어가는 기준을 찾아보고 규칙을 찾자
2/8/20/38/62
6/12/18/24 --------- 역시 이런 문제들은 대부분 n의 배수 차열로 나타내진다.
따라서 위 기준을 나타내려면 2+3n(n+1) 으로 표현이 가능하다
- Solution
함수을 이용한 풀이
def c(a):
return 6*sum(range(a))+2
d = int(input())
if d==1:
print(1)
for n in range(BIG NUMBER):
if d<c(n+1) and d>=c(n):
print(n+1)
코드를 읽어보면 처음 문제를 받고 어느정도 이해를 했을때 고등학교 때 f(x)와 f(x+1) 를 이용해서 풀었던 등차 수열임을 알 수 있는데 코드 상의 논리에 대한 오류는 없지만 실제로 이 풀이를 제출하게되면 시간 초과가 뜬다 중간에 조건에 맞는 n을 찾으면 break 를 하라는 조건을 추가해도 좋지만 이 코드는 너무 많은 자원을 소비 하게 된다. 나쁜 코드는 아니지만 사용을 지양해야되는 알고리즘 코딩 방식인 것이다.
따라서 if 대신에 while 문을 넣고 함수 대신에 기존의 변수에 계속해서 업데이트(6의 배수)를 해주는 방식으로 짜보았다.
while() 문과 변수의 업데이팅을 이용한 풀이
d = int(input())
n=1
a=2
while d>=a:
a=a+6*n
n+=1
print(n)
코드도 간단해졌고 이해도 쉬워졌다! 고등수학이 아닌 코딩에선 변수를 계속 업데이트 해보는 방식도 생각해보자
분수찾기(#1193)
- Problem
무한히 큰 배열에 다음과 같이 분수들이 적혀있다.
이와 같이 나열된 분수들을 1/1 → 1/2 → 2/1 → 3/1 → 2/2 → … 과 같은 지그재그 순서로 차례대로 1번, 2번, 3번, 4번, 5번, … 분수라고 하자. X가 주어졌을 때, X번째 분수를 구하는 프로그램을 작성하시오.
- Hint
지그재그로 반복된다는 것이 짝수번은 위에서 아래로 홀수번은 아래에서 위로 나열된다는 것이다,
- Solution
while()을 이용한 풀이
a= int(input())
d=0
n=0
while a>d:
n+=1
d=d+n
if n%2==1:
print(f'{n+1-(a-d+n)}/{a-d+n}')
else:
print(f'{a-d+n}/{n+1-(a-d+n)}')
출력 방식이 복잡해보이지만 이해가 잘되도록 늘여서 써놓았다.
달팽이는 올라가고 싶다(#2869)
- Problem
땅 위에 달팽이가 있다. 이 달팽이는 높이가 V미터인 나무 막대를 올라갈 것이다. 달팽이는 낮에 A미터 올라갈 수 있다. 하지만, 밤에 잠을 자는 동안 B미터 미끄러진다. 또, 정상에 올라간 후에는 미끄러지지 않는다. 달팽이가 나무 막대를 모두 올라가려면, 며칠이 걸리는지 구하는 프로그램을 작성하시오.
- Hint
미리 미끄러진 길이를 생각하여 풀었다.
- Solution
import math
a,b,v=map(int,input().split())
v= v-b
print(math.ceil(v/(a-b)))
일단 올림을 사용하기 위해 math를 추가해주었다.
미끄러지는 길이는 항상 올라가는 길이보다 작으니까 빼줘도 그 다음날에는 무조건 도착을 한다. 하루에 올라가는 길이 (올라가는 길이-내려오는 길이) 를 나누면경우 1 : 나누어 떨어진다 -> 다음날에 올라가는거니 상관없다경우 2 : 남는다 -> (하루에 올라가는 길이보다 작은 길이)만큼 남았기 때문에 하루가 더 필요하다.
두 경우를 나누어 떨어질 경우(=나머지가 없는경우 if) 를 사용하여 나누어 주어도 되지만 그렇게 되면 자원을 많이 사용하기 때문에 우리는 나머지가 있는경우 올림을 하도록 하는 전략을 사용하였다.
ACM 호텔(#10250)
- Problem
ACM 호텔 매니저 지우는 손님이 도착하는 대로 빈 방을 배정하고 있다. 고객 설문조사에 따르면 손님들은 호텔 정문으로부터 걸어서 가장 짧은 거리에 있는 방을 선호한다고 한다. 여러분은 지우를 도와 줄 프로그램을 작성하고자 한다. 즉 설문조사 결과 대로 호텔 정문으로부터 걷는 거리가 가장 짧도록 방을 배정하는 프로그램을 작성하고자 한다. 문제를 단순화하기 위해서 호텔은 직사각형 모양이라고 가정하자. 각 층에 W 개의 방이 있는 H 층 건물이라고 가정하자 (1 ≤ H, W ≤ 99). 그리고 엘리베이터는 가장 왼쪽에 있다고 가정하자(그림 1 참고). 이런 형태의 호텔을 H × W 형태 호텔이라고 부른다. 호텔 정문은 일층 엘리베이터 바로 앞에 있는데, 정문에서 엘리베이터까지의 거리는 무시한다. 또 모든 인접한 두 방 사이의 거리는 같은 거리(거리 1)라고 가정하고 호텔의 정면 쪽에만 방이 있다고 가정한다.
그림 1. H = 6 이고 W = 12 인 H × W 호텔을 간략하게 나타낸 그림 방 번호는 YXX 나 YYXX 형태인데 여기서 Y 나 YY 는 층 수를 나타내고 XX 는 엘리베이터에서부터 세었을 때의 번호를 나타낸다. 즉, 그림 1 에서 빗금으로 표시한 방은 305 호가 된다. 손님은 엘리베이터를 타고 이동하는 거리는 신경 쓰지 않는다. 다만 걷는 거리가 같을 때에는 아래층의 방을 더 선호한다. 예를 들면 102 호 방보다는 301 호 방을 더 선호하는데, 102 호는 거리 2 만큼 걸어야 하지만 301 호는 거리 1 만큼만 걸으면 되기 때문이다. 같은 이유로 102 호보다 2101 호를 더 선호한다. 여러분이 작성할 프로그램은 초기에 모든 방이 비어있다고 가정하에 이 정책에 따라 N 번째로 도착한 손님에게 배정될 방 번호를 계산하는 프로그램이다. 첫 번째 손님은 101 호, 두 번째 손님은 201 호 등과 같이 배정한다. 그림 1 의 경우를 예로 들면, H = 6이므로 10 번째 손님은 402 호에 배정해야 한다.
- Hint
6, 3, 12의 케이스를 생각해보자
- Solution
문자열로의 변환을 이용한 풀이
import math
n=int(input())
result=[]
for i in range(n):
a,b,c=map(int,input().split())
b=str(math.ceil(c/a)).zfill(2)
if c%a==0:
f=a
else:
f=c%a
cd=str(f)+b
result.append(int(cd))
print(*result, sep='\n')
.zfill 을 통하여 호수가 한자리 수일때 앞의 자리에 0을 추가해주도록 했다.
int()형으로의 풀이
n=int(input())
result=[]
for i in range(n):
a,b,c=map(int,input().split())
f=(c-1)%a+1
b=(c-1)//a+1
result.append(f*100+b)
print(*result, sep='\n')
최상층을 표현하기 위해 사용했던 식도 (c-1), 올림 전체 수에서 1을 빼주는 테크닉으로 사용하지 않았다.
부녀회장이 될테야(#2775)
- Problem
평소 반상회에 참석하는 것을 좋아하는 주희는 이번 기회에 부녀회장이 되고 싶어 각 층의 사람들을 불러 모아 반상회를 주최하려고 한다. 이 아파트에 거주를 하려면 조건이 있는데, “a층의 b호에 살려면 자신의 아래(a-1)층의 1호부터 b호까지 사람들의 수의 합만큼 사람들을 데려와 살아야 한다” 는 계약 조항을 꼭 지키고 들어와야 한다. 아파트에 비어있는 집은 없고 모든 거주민들이 이 계약 조건을 지키고 왔다고 가정했을 때, 주어지는 양의 정수 k와 n에 대해 k층에 n호에는 몇 명이 살고 있는지 출력하라. 단, 아파트에는 0층부터 있고 각층에는 1호부터 있으며, 0층의 i호에는 i명이 산다.
- Hint
규칙을 잘 찾지 못할때는 예시를 써놓고 생각을 해보자
- Solution
맨 위에 1 1 1 1 로 이루어진 행렬을 하나 더 만들어주고 나면 전체에서 어느 셀의 값은 그 밑에 있는 행렬의 합임을 알 수 있다. ks를 층으로 hs 을 호수로 두었다.
n= int(input())
result=[]
for i in range(n):
ks= int(input())
hs= int(input())
r=[int(1)]*hs
td=[]*hs
for k in range(ks+1):
for h in range(hs):
r[hs-1-h]=sum(r[0:hs-h])
res=r[hs-1]
result.append(res)
print(*result,sep='\n')
자원을 아끼고 싶어서 r[] 리스트를 계속 갱신을 해주는 방식을 사용했는데 리스트의 뒤부터 변환을 시켜주어 한 층의 계산이 끝날때까지 계산 유효값에 영향을 끼치지 않게 하였다.
이후에 결과값은 result에 저장하였다.
contents 02
설탕 배달(#2839)
- Problem
상근이는 요즘 설탕공장에서 설탕을 배달하고 있다. 상근이는 지금 사탕가게에 설탕을 정확하게 N킬로그램을 배달해야 한다. 설탕공장에서 만드는 설탕은 봉지에 담겨져 있다. 봉지는 3킬로그램 봉지와 5킬로그램 봉지가 있다. 상근이는 귀찮기 때문에, 최대한 적은 봉지를 들고 가려고 한다. 예를 들어, 18킬로그램 설탕을 배달해야 할 때, 3킬로그램 봉지 6개를 가져가도 되지만, 5킬로그램 3개와 3킬로그램 1개를 배달하면, 더 적은 개수의 봉지를 배달할 수 있다. 상근이가 설탕을 정확하게 N킬로그램 배달해야 할 때, 봉지 몇 개를 가져가면 되는지 그 수를 구하는 프로그램을 작성하시오.
- Hint
규칙으로 골라낼수 없는 인자가 2개가 있다. 이를 찾아내야한다.
- Solution
3의 배수 특징을 이용한 풀이
res=0
n= int(input())
if n in [4,7]:
res=-1
elif n%5==0:
res=n//5
elif n%5%2==1:
res=n//5+1
elif n%5%2==0:
res=n//5+2
print(res)
4, 7 이 제외된다는 사실을 알고 있어야한다. 3과 5의 조합은 짝수와 홀수의 조합으로 직관적으로 생각해보면 둘의 합과 차이가 1이 나오는 숫자 이후로는 모든 숫자가 조합 가능하지만 (최초의 1 : 5+5 - (3+3+3) ) 그 전에는 조합 불가한 숫자도 존재하게 된다. 그리고 뒤의 케이스 나누는 방식은
이런 생각을 통해 보정값을 더해주는 방식으로 하였다. 나머지가 홀수 짝수 일 경우 0인 경우는 간섭을 피하기 위해 elif 의 최상단에 넣어주었다.
숏코딩
n = int(input())
print(-(n in [4, 7]) or n-2*n//5*2)
엄청난 수식이 들어간것 같다고 무서워 할 필요가 없다 4,7을 제외시키고 뒤에 있는 식은 결국 위에 풀이한 방법을 식으로 간단히 정리한 것 뿐이다. 3의 배수의 1의 자리수 규칙과 trim 과 잘 비교해보면 이해가 가능하다.
큰 수 A+B(#10757)
- Problem
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
- Hint
리스트를 이용하여 계산해보자, 자리수를 유의하여 생각해본다.
- Solution
리스트를 이용한 풀이
res=[]
u=0
a,b=map(str,input().split())
a= a.zfill(max(len(a),len(b)))
b= b.zfill(max(len(a),len(b)))
for i in range(min(len(a),len(b))):
d=int(a[::-1][i])+int(b[::-1][i])+u
if d>=10:
res.append(d%10)
u=1
if i==min(len(a),len(b))-1:
res.append(1)
else:
res.append(d)
u=0
print(*res[::-1],sep='')
res에 결과값을 역순으로 추가해주고 u를 overflow carry 비트로 사용하였다.
덧셈을 할 시에는 뒤에서 부터 계산하는것이 용이하기 떄문에 [::-1] 을 이용하여 역산 해주었고
max(len(a),len(b)) 를 통하여 서로 자리수가 다른 경우에 자리수를 맞춰주었다.
또한 최고자리의 올림수 1을 위해 반복문이 (i가 마지막까지 반복되었을때도 10이 넘는 결과가 나왔다면 1을 추가해주는 방식으로 구현하였다.)
'Baekjoon > Stepbystep' 카테고리의 다른 글
[백준/python] 재귀 전체 풀이(9단계) (0) | 2022.08.04 |
---|---|
[백준/python] 기본 수학 2 전체 풀이(8단계) (0) | 2022.08.02 |
[백준/python] 문자열 전체 풀이(6단계) (0) | 2022.07.31 |
[백준/python] 함수 전체 풀이(5단계) (0) | 2022.07.29 |
[백준/python] 1차원 배열 전체 풀이(4단계) (0) | 2022.07.29 |