본문 바로가기
Algorithm/백준

[Python] 백준 1654번 - 랜선 자르기

by 애기 개발자 2022. 11. 2.
반응형

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

 

1654번: 랜선 자르기

첫째 줄에는 오영식이 이미 가지고 있는 랜선의 개수 K, 그리고 필요한 랜선의 개수 N이 입력된다. K는 1이상 10,000이하의 정수이고, N은 1이상 1,000,000이하의 정수이다. 그리고 항상 K ≦ N 이다. 그

www.acmicpc.net

 

문제

집에서 시간을 보내던 오영식은 박성원의 부름을 받고 급히 달려왔다. 박성원이 캠프 때 쓸 N개의 랜선을 만들어야 하는데 너무 바빠서 영식이에게 도움을 청했다.

이미 오영식은 자체적으로 K개의 랜선을 가지고 있다. 그러나 K개의 랜선은 길이가 제각각이다. 박성원은 랜선을 모두 N개의 같은 길이의 랜선으로 만들고 싶었기 때문에 K개의 랜선을 잘라서 만들어야 한다. 예를 들어 300cm 짜리 랜선에서 140cm 짜리 랜선을 두 개 잘라내면 20cm는 버려야 한다. (이미 자른 랜선은 붙일 수 없다.)

편의를 위해 랜선을 자르거나 만들 때 손실되는 길이는 없다고 가정하며, 기존의 K개의 랜선으로 N개의 랜선을 만들 수 없는 경우는 없다고 가정하자. 그리고 자를 때는 항상 센티미터 단위로 정수길이만큼 자른다고 가정하자. N개보다 많이 만드는 것도 N개를 만드는 것에 포함된다. 이때 만들 수 있는 최대 랜선의 길이를 구하는 프로그램을 작성하시오.

입력

첫째 줄에는 오영식이 이미 가지고 있는 랜선의 개수 K, 그리고 필요한 랜선의 개수 N이 입력된다. K는 1이상 10,000이하의 정수이고, N은 1이상 1,000,000이하의 정수이다. 그리고 항상 K ≦ N 이다. 그 후 K줄에 걸쳐 이미 가지고 있는 각 랜선의 길이가 센티미터 단위의 정수로 입력된다. 랜선의 길이는 231-1보다 작거나 같은 자연수이다.

출력

첫째 줄에 N개를 만들 수 있는 랜선의 최대 길이를 센티미터 단위의 정수로 출력한다.

 

 


위 문제는 기존에 풀었던 떡 자르기 문제와 비슷하다.

 

2022.10.17 - [Algorithm/이것이 코딩테스트다] - [Python][이코테] 떡볶이 떡 만들기

 

[Python][이코테] 떡볶이 떡 만들기

오늘 동빈이는 여행가신 부모님을 대신해서 떡집 일을 하기로 했다. 오늘은 떡볶이 떡을 만드는 날이다. 동빈이네 떡볶이 떡은 재밌게도 떡볶이 떡의 길이가 일정하지 않다. 대신에 한 봉지 안

baby-dev.tistory.com

 

가장 긴 길이를 max로 잡고 이분탐색을 진행한다.

 

(정답 코드는 제일 아래)

 

우선 내가 틀린 코드부터 확인하겠다.

 

먼저 기존의 이분 탐색과 동일한 방법으로 문제를 풀었었다.

 

import sys
k, n = map(int, sys.stdin.readline().split())
line = []
for _ in range(k):
  line.append(int(sys.stdin.readline()))

start = 0
end = max(line)

while start <= end:
  mid = (start + end) // 2
  length = 0
  for i in line:
    length += i // mid
  if length == n:
    print(mid)
    break
  elif length < n:
    end = mid -1
  else:
    start = mid + 1

길이를 구해서 같으면 출력,

길면 end 자르고 / 짧으면 start 잘라주는 식으로

 

하지만 백준에서 5%구간에서 계속 틀렸습니다. 를 마주하게 되었다.

 

그래서 문제를 다시 보니 자를 수 있는 최댓값을 구하는 것이다.

 

import sys
k, n = map(int, sys.stdin.readline().split())
line = []
for _ in range(k):
  line.append(int(sys.stdin.readline()))

start = 0
end = max(line)

while start <= end:
  mid = (start + end) // 2
  length = 0
  for i in line:
    length += i // mid
  if length < n:
    end = mid -1
  else:
    start = mid+1
print(end)

위와 바뀐 부분은 기존의

 

 if length == n 부분을 >= 으로 바꾸면서 start와 end가 교차될 마지막 부분까지를 확인한 것이다.

 

이렇게 되면 가장 최대길이의 값을 구할 수 있게 된다.

 

하지만... 하나 간과한 것이 있었다.

 

위의 코드는

 

0을 나누기를 시도한 에러가 발생한 것이다.

 

0을 나눌 구간은 도저히 못 찾겠어서... 결국 인터넷에 검색해봤다.

 

차이점은  start = 1로 시작한다는 것이었다.

 

import sys
k, n = map(int, sys.stdin.readline().split())
line = []
for _ in range(k):
  line.append(int(sys.stdin.readline()))

start = 1
end = max(line)

while start <= end:
  mid = (start + end) // 2
  length = 0
  for i in line:
    length += i // mid
  if length < n:
    end = mid -1
  else:
    start = mid+1
print(end)

어떻게.. start가 0일 때 에러가 발생하는지 잘 모르겠다... end가 1인 값이라도 있는 건가...

 

1 // 2는 0 이 되고 0으로 나누려 하면 에러가 발생할 수 있으니 말이다.

 

 

반응형

댓글