문제:

세계적인 도둑 상덕이는 보석점을 털기로 결심했다.

상덕이가 털 보석점에는 보석이 총 N개 있다. 각 보석은 무게 Mi와 가격 Vi를 가지고 있다. 상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 Ci이다. 가방에는 최대 한 개의 보석만 넣을 수 있다.

상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000)

다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000)

다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci ≤ 100,000,000)

모든 숫자는 양의 정수이다.

출력:

첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.

풀이방법:

 우선순위 큐(heapq)를 사용해서 가방에 최대한 비싼 보석을 그리디하게 넣는다 생각하면 된다. 따라서 보석의 정보들을 무게가 가벼운 순으로 heapq를 통해서 정렬하고, 가방도 오름차순으로 정렬을 한다.

 정렬을 마친 뒤에 가벼운 가방으로부터 시작하여 해당 가방에 넣을 수 있는 보석들을 최대힙으로 다시 구현을 한 뒤에 그 최대힙에서 가장 큰 값을 뽑아 answer에 더해준다. 이와 같은 과정들을 모든 가방에 대해 수행을 하며, 최대힙과 최소힙은 계속해서 누적해서 사용하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import heapq
import copy
 
N, K = map(int,input().split())
= []
 
for _ in range(N):
    m, v = map(int,input().split())
    heapq.heappush(h,(m,v))
    
bags = []
for _ in range(K):
    bags.append(int(input()))
    
bags.sort()
 
answer = 0
ans = []
for bag in bags:
    while (h and h[0][0]<=bag):
        heapq.heappush(ans,-heapq.heappop(h)[-1])
    if ans:
        answer += -heapq.heappop(ans)
    elif not h:
        break
print(answer)
cs

문제링크:

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

 

1202번: 보석 도둑

첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000) 다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000) 다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1722. 순열의 순서  (0) 2021.09.27
[BOJ]1351. 무한 수열  (0) 2021.09.24
[BOJ]1057. 토너먼트  (0) 2021.09.16
[BOJ] 14890. 경사로  (0) 2021.09.15
[BOJ]14719. 빗물  (0) 2021.09.14

문제:

수빈이는 동생에게 "가운데를 말해요" 게임을 가르쳐주고 있다. 수빈이가 정수를 하나씩 외칠때마다 동생은 지금까지 수빈이가 말한 수 중에서 중간값을 말해야 한다. 만약, 그동안 수빈이가 외친 수의 개수가 짝수개라면 중간에 있는 두 수 중에서 작은 수를 말해야 한다.

예를 들어 수빈이가 동생에게 1, 5, 2, 10, -99, 7, 5를 순서대로 외쳤다고 하면, 동생은 1, 1, 2, 2, 2, 2, 5를 차례대로 말해야 한다. 수빈이가 외치는 수가 주어졌을 때, 동생이 말해야 하는 수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에는 수빈이가 외치는 정수의 개수 N이 주어진다. N은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수이다. 그 다음 N줄에 걸쳐서 수빈이가 외치는 정수가 차례대로 주어진다. 정수는 -10,000보다 크거나 같고, 10,000보다 작거나 같다.

출력:

한 줄에 하나씩 N줄에 걸쳐 수빈이의 동생이 말해야하는 수를 순서대로 출력한다.

풀이방법:

시간 제한이 매우 엄격하게 정해져 있기 때문에 max_heap과 min_heap를 두 개를 사용해서 중간값을 구하도록 한다. 기본적인 아이디어는 양쪽에 채워나가면서 heap으로 정리했을 때, 가운데 값을 기준으로 정렬되는 것을 이용한다. max_heap에는 중간값보다 낮은 값들을 채워나가고, min_heap은 중간값보다 큰 값이 채워지도록 하게 한다. 개수가 짝수개인 경우 두 수 중에 작은 수를 말해야 하기 때문에 max_heap에 있는 값을 출력하도록 한다.  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import heapq
= int(input())
max_h = []
min_h = []
for i in range(N):
    tmp = int(input())
    if len(min_h)==len(max_h):
        heapq.heappush(max_h,(-tmp,tmp))
    else:
        heapq.heappush(min_h, tmp)
    if len(max_h) and len(min_h) and max_h[0][1> min_h[0]:
        a, b = heapq.heappop(max_h)[1], heapq.heappop(min_h)
        heapq.heappush(max_h,(-b,b))
        heapq.heappush(min_h,a)
    print(max_h[0][1])
cs

문제링크:

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

 

1655번: 가운데를 말해요

첫째 줄에는 수빈이가 외치는 정수의 개수 N이 주어진다. N은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수이다. 그 다음 N줄에 걸쳐서 수빈이가 외치는 정수가 차례대로 주어진다. 정수는 -1

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]14719. 빗물  (0) 2021.09.14
[BOJ]2470. 두 용액  (0) 2021.09.13
[BOJ]2110. 공유기 설치  (0) 2021.09.09
[BOJ]17406. 배열 돌리기 4  (0) 2021.09.08
[BOJ]2638. 치즈  (0) 2021.09.06

문제:

성경이는 트럭을 정글 속에서 운전하다가 트럭의 연료탱크에 갑자기 구멍이 나서 1km를 가는데 1L의 연료가 새 나가게 되었다. 이것을 고치기 위해서는 가장 가까운 마을에 가야 한다. 그런데 그냥 가다가는 중간에 연료가 다 빠질 수가 있다. 다행스럽게도 정글 곳곳에 연료를 채울 수 있는 주유소가 N개 있다. 그런데 정글 속에서 중간에 차를 멈추는 행위는 매우 위험한 행위이므로 주유소에서 멈추는 횟수를 최소화 하려 한다.

그리고 다행이도 성경이의 트럭은 매우 좋아서 연료 탱크에는 연료의 제한이 없이 많이 충분히 많이 넣을 수 있다고 한다. 각각의 주유소의 위치와, 각 주유소에서 얻을 수 있는 연료의 양이 주어져 있을 때, 주유소에서 멈추는 횟수를 구하는 프로그램을 작성하시오.

정글은 일직선이고, 성경이의 트럭과 주유소도 모두 일직선 위에 있다. 주유소는 모두 성경이의 트럭을 기준으로 오른쪽에 있다.

입력:

첫째 줄에 주유소의 개수 N(1 ≤ N ≤ 10,000)가 주어지고 두 번째 줄부터 N+1번째 줄 까지 주유소의 정보가 주어진다. 주유소의 정보는 두개의 정수 a,b로 이루어 져 있는데 a(1 ≤ a ≤ 1,000,000)는 성경이의 시작 위치에서 주유소 까지의 거리, 그리고 b(1 ≤ b ≤ 100)는 그 주유소에서 채울 수 있는 연료의 양을 의미한다. 그리고 N+2번째 줄에는 두 정수 L과 P가 주어지는데 L(1 ≤ L ≤ 1,000,000)은 성경이의 위치에서 마을까지의 거리, (1 ≤ P ≤ 1,000,000)는 트럭에 원래 있던 연료의 양을 의미한다.

출력:

첫째 줄에 주유소에서 멈추는 횟수를 출력한다. 만약 마을에 도착하지 못할경우 -1을 출력한다.

풀이방법:

1. 우선순위 큐를 사용해서 연료 내에서 움직일 수 있는 주유소에서 주유하도록 한다.

2. 데이터를 전처리할 때, 거리는 작은 순으로 주어지지 않는다. 정렬이 필요하다

3. 마을에 도착하지 못하는 경우는 while에 있지만 더 이상 움직이지 못할 때를 의미한다. (candidates가 비어있는 경우)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import heapq
def solution(move, dist, fuels, town):
    candidates = []
    cnt = 0
    location = 0
    while move < town:
        for i in range(location, len(dist)):
            if dist[i] <= move:
                f = fuels[i]
                heapq.heappush(candidates, (-f, f))
                location = i+1
            else:
                break
        if not len(candidates):
            cnt = -1
            break
        cnt += 1
        move += heapq.heappop(candidates)[1]
    return cnt
 
dist_ = []
fuel_ = []
temp= []
= int(input())
for _ in range(n):
    dist, fuel = map(int,input().split())
    temp.append((dist,fuel))
    
temp.sort()
for i in range(len(temp)):
    dist_.append(temp[i][0])
    fuel_.append(temp[i][1])
    
len_, start = map(int,input().split())
answer = solution(start,dist_,fuel_,len_)
print(answer)
cs

문제링크:

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

 

1826번: 연료 채우기

첫째 줄에 주유소의 개수 N(1 ≤ N ≤ 10,000)가 주어지고 두 번째 줄부터 N+1번째 줄 까지 주유소의 정보가 주어진다. 주유소의 정보는 두개의 정수 a,b로 이루어 져 있는데 a(1 ≤ a ≤ 1,000,000)는 성경

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2302. 극장 좌석  (0) 2021.06.03
[BOJ]1024. 수열의 합  (0) 2021.06.01
[BOJ]1422. 숫자의 신  (0) 2021.05.25
[BOJ]15686. 치킨 배달  (0) 2021.05.20
[BOJ]2583. 영역 구하기  (0) 2021.05.18

문제:

라면 공장에서는 하루에 밀가루를 1톤씩 사용합니다. 원래 밀가루를 공급받던 공장의 고장으로 앞으로 k일 이후에야 밀가루를 공급받을 수 있기 때문에 해외 공장에서 밀가루를 수입해야 합니다.

해외 공장에서는 향후 밀가루를 공급할 수 있는 날짜와 수량을 알려주었고, 라면 공장에서는 운송비를 줄이기 위해 최소한의 횟수로 밀가루를 공급받고 싶습니다.

현재 공장에 남아있는 밀가루 수량 stock, 밀가루 공급 일정(dates)과 해당 시점에 공급 가능한 밀가루 수량(supplies), 원래 공장으로부터 공급받을 수 있는 시점 k가 주어질 때, 밀가루가 떨어지지 않고 공장을 운영하기 위해서 최소한 몇 번 해외공장으로부터 밀가루를 공급받아야 하는지를 return 하도록 solution 함수를 완성하세요.

dates[i]에는 i번째 공급 가능일이 들어있으며, supplies[i]에는 dates[i] 날짜에 공급 가능한 밀가루 수량이 들어 있습니다.

풀이 방법:

stock의 합이 k를 넘어가면 더이상 공급을 받지 않아도 된다. 그러므로 while의 조건을 stock<k 으로 잡았다. 기본적으론 남아있는 stock에 따라서 공급을 받을 수 있는 양이 다르게 된다. 예시에서와 같이 초기 stock이 4이므로 dates의 4일째인 20을 받을 수밖에 없다. 만약 기간 내에 여러 개의 날에서 공급을 받을 수 있다면 가장 많은 양을 받아오는 것이 적게 공급을 받도록 할 수 있다. 따라서 이 과정에서 우선순위 큐, 즉 힙을 사용하게 된다. stock에 따라서 받을 수 있는 공급들을 리스트에 담고 인덱스를 저장한다. 그리고 이 리스트 중에서 가장 많은 공급의 양을 빼서 stock에 더한다.
python에서 heapq라는 모듈을 제공해서 힙구조를 만들 수 있도록 한다. 하지만 이 힙은 최소힙을 제공하므로 힙구조에서 pop을 했을 때 최솟값이 나오게 된다. 하지만 이 문제에서는 최댓값을 빼야 하므로 최대 힙을 만들도록 한다. 따라서 힙에 넣을 당시에 heapq.heappush(h,(-supplies[i],supplies[i])) 와 같이 넣어서 최대힙을 구성하도록 하고 stock+=heapq.heappop(h)[1] 로 값을 빼도록 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import heapq
def solution(stock, dates, supplies, k):
    answer = 0
    idx=0
    h=[]
    while(stock<k):
        for i in range(idx,len(dates)):
            if dates[i]<=stock:
                heapq.heappush(h,(-supplies[i],supplies[i]))
                idx=i+1
            else:
                break
        stock+=heapq.heappop(h)[1]
        answer+=1
    return answer
cs


'Algorithm > Python' 카테고리의 다른 글

[BOJ]2839.설탕 배달  (1) 2019.03.31
[BOJ]11718.그대로 출력하기  (0) 2019.03.30
[Programmers]Lv 2. 영어 끝말잇기  (0) 2019.03.28
[Programmers]Lv 2. 점프와 순간이동  (0) 2019.03.27
[Programmers]Lv 2.소수 만들기  (0) 2019.03.26

+ Recent posts