문제:

게임 개발자인 밀리는 전투력 시스템을 만들어, 캐릭터가 가진 전투력을 기준으로 칭호를 붙여주려고 한다.

예를 들어, 전투력 10,000 이하의 캐릭터는 WEAK, 10,000 초과 그리고 100,000 이하의 캐릭터는 NORMAL, 100,000 초과 그리고 1,000,000 이하의 캐릭터는 STRONG 칭호를 붙여준다고 하자. 이를 IF문으로 작성한다면 아래와 같이 구현할 수 있다.

if power <= 10000
 print WEAK
else if power <= 100000
 print NORMAL
else if power <= 1000000
 print STRONG

혼자서 게임을 개발하느라 매우 바쁜 밀리를 대신해서, 캐릭터의 전투력에 맞는 칭호를 출력하는 프로그램을 작성하자.

입력:

첫 번째 줄에는 칭호의 개수 N (1 ≤ N ≤ 105)과 칭호를 출력해야 하는 캐릭터들의 개수 M (1 ≤ M ≤ 105)이 빈칸을 사이에 두고 주어진다. (1 ≤ N, M ≤ 105)

두 번째 줄부터 N개의 줄에 각 칭호의 이름을 나타내는 길이 1 이상, 11 이하의 영어 대문자로만 구성된 문자열과 해당 칭호의 전투력 상한값을 나타내는 109 이하의 음이 아닌 정수가 주어진다. 칭호는 전투력 상한값의 비내림차순으로 주어진다. 

N + 2번째 줄부터 M개의 각 줄에는 캐릭터의 전투력을 나타내는 음이 아닌 정수가 주어진다. 해당하는 칭호가 없는 전투력은 입력으로 주어지지 않는다.

출력:

M개의 줄에 걸쳐 캐릭터의 전투력에 맞는 칭호를 입력 순서대로 출력한다. 어떤 캐릭터의 전투력으로 출력할 수 있는 칭호가 여러 개인 경우 가장 먼저 입력된 칭호 하나만 출력한다.

풀이방법:

 N, M의 범위가 많이 크기 때문에 일반적인 탐색을 사용한다면 시간초과가 발생하게 된다. 따라서 더 빠른 탐색을 사용하여 이분탐색을 사용하도록 한다.

 따라서 python에는 이분탐색을 도와주는 bisect가 있기 때문에 이를 사용할 수 있다. 이 문제는 이분 탐색을 수행하고, 주어진 M을 왼쪽에 삽입하는 것과 같기 때문에 bisect_left 함수를 사용하도록 한다. 주어진 M이 이분 탐색에 의해 삽입될 인덱스를 구하게 된다면, 그 인덱스에 해당하는 칭호의 이름을 출력하도록 한다.

 그리고 출력 조건에서 칭호가 여러 개인 경우 가장 먼저 입력된 칭호 하나를 출력해야 하는데, 입력이 애초에 오름차순으로 주어지기 때문에 따로 고려할 점은 없다.

1
2
3
4
5
6
7
8
9
10
11
12
import bisect
N, M = map(int, input().split())
 
style, number = [], []
for _ in range(N):
    s, n = input().split()
    style.append(s)
    number.append(int(n))
 
for _ in range(M):
    m = int(input())
    print(style[bisect.bisect_left(number, m)])
cs

문제링크:

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

 

19637번: IF문 좀 대신 써줘

첫 번째 줄에는 칭호의 개수 N (1 ≤ N ≤ 105)과 칭호를 출력해야 하는 캐릭터들의 개수 M (1 ≤ M ≤ 105)이 빈칸을 사이에 두고 주어진다. (1 ≤ N, M ≤ 105) 두 번째 줄부터 N개의 줄에 각 칭

www.acmicpc.net

 

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

[BOJ] 3759. KCPC  (0) 2023.07.31
[Programmers] Lv 2. 점 찍기  (0) 2023.07.27
[BOJ] 2607. 비슷한 단어  (0) 2023.07.26
[Programmers]Lv 2. 호텔 대실  (0) 2023.07.25
[BOJ] 1515. 수 이어 쓰기  (0) 2023.07.24

문제:

개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이 번갈아가면서 등장한다.

아래 그림은 길이가 14미터이고 높이가 5미터인 동굴이다. (예제 그림)

이 개똥벌레는 장애물을 피하지 않는다. 자신이 지나갈 구간을 정한 다음 일직선으로 지나가면서 만나는 모든 장애물을 파괴한다.

위의 그림에서 4번째 구간으로 개똥벌레가 날아간다면 파괴해야하는 장애물의 수는 총 여덟개이다. (4번째 구간은 길이가 3인 석순과 길이가 4인 석순의 중간지점을 말한다)

하지만, 첫 번째 구간이나 다섯 번째 구간으로 날아간다면 개똥벌레는 장애물 일곱개만 파괴하면 된다.

동굴의 크기와 높이, 모든 장애물의 크기가 주어진다. 이때, 개똥벌레가 파괴해야하는 장애물의 최솟값과 그러한 구간이 총 몇 개 있는지 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 N과 H가 주어진다. N은 항상 짝수이다. (2 ≤ N ≤ 200,000, 2 ≤ H ≤ 500,000)

다음 N개 줄에는 장애물의 크기가 순서대로 주어진다. 장애물의 크기는 H보다 작은 양수이다.

출력:

첫째 줄에 개똥벌레가 파괴해야 하는 장애물의 최솟값과 그러한 구간의 수를 공백으로 구분하여 출력한다.

풀이방법:

이분 탐색을 사용하여, 빠르게 인덱스를 찾도록 한다. 석순과 종유석을 각자의 배열에 담고, 이들을 정렬한다. 그리고 H를 늘려가며, 부셔야 하는 갯수를 찾는데, 개똥벌레는 정수의 높이로 날라가는 것이 아닌 0.5 지점을 날기 때문에 이를 고려하여 인덱스를 찾아야 한다. 종유석과 석순 개별적으로 부셔야 하는 갯수를 찾은 뒤 이들의 합이 가장 작을 때를 찾도록 한다.

 만약 최솟값이 여러번 나오는 경우에는 이를 누적해서 더해주고, 만약 새로운 최솟값이 나오면 누적 합을 초기화시켜준다.

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
import bisect
import sys
 
input=sys.stdin.readline
N, H = map(int,input().split())
min_count = N
range_answer = 0
 
obstacle_d = []
obstacle_u = []
 
for i in range(N):
    if i%2:
        obstacle_u.append(int(input()))
    else:
        obstacle_d.append(int(input()))
 
obstacle_d.sort()
obstacle_u.sort()
 
for i in range(1, H+1):
    down_count = len(obstacle_d) - bisect.bisect_left(obstacle_d, i-0.5)
    up_count = len(obstacle_u) - bisect.bisect_left(obstacle_u, H-(i-0.5))
    if min_count == down_count+up_count:
        range_answer+=1
    elif min_count > down_count+up_count:
        min_count = down_count+up_count
        range_answer = 1
 
        print(min_count,range_answer)
cs

문제링크:

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

 

3020번: 개똥벌레

개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이

www.acmicpc.net

 

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

[BOJ] 10157. 자리배정  (0) 2021.10.05
[BOJ] 1019. 책 페이지  (0) 2021.10.01
[BOJ]6593. 상범 빌딩  (0) 2021.09.29
[BOJ]12904. A와 B  (0) 2021.09.28
[BOJ]1722. 순열의 순서  (0) 2021.09.27

문제:

도현이의 집 N개가 수직선 위에 있다. 각각의 집의 좌표는 x1, ..., xN이고, 집 여러개가 같은 좌표를 가지는 일은 없다.

도현이는 언제 어디서나 와이파이를 즐기기 위해서 집에 공유기 C개를 설치하려고 한다. 최대한 많은 곳에서 와이파이를 사용하려고 하기 때문에, 한 집에는 공유기를 하나만 설치할 수 있고, 가장 인접한 두 공유기 사이의 거리를 가능한 크게 하여 설치하려고 한다.

C개의 공유기를 N개의 집에 적당히 설치해서, 가장 인접한 두 공유기 사이의 거리를 최대로 하는 프로그램을 작성하시오.

입력:

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (0 ≤ xi ≤ 1,000,000,000)가 한 줄에 하나씩 주어진다.

출력:

첫째 줄에 가장 인접한 두 공유기 사이의 최대 거리를 출력한다.

풀이방법:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
N, C = map(int,input().split())
house = sorted([int(input()) for _ in range(N)])
answer = 0
right = house[-1]-house[0]
left = 1
 
while left <= right:
    mid = (left + right)//2
    cur = house[0]
    count = 1
    for i in range(1,len(house)):
        if house[i] >= cur + mid:
            count+=1
            cur = house[i]
    if count >= C:
        left = mid + 1
        answer = mid
    else:
        right = mid - 1
        
print(answer)
cs

문제링크:

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

 

2110번: 공유기 설치

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (0 ≤ xi ≤ 1,000,000,000)가

www.acmicpc.net

 

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

[BOJ]2470. 두 용액  (0) 2021.09.13
[BOJ]1655. 가운데를 말해요  (0) 2021.09.10
[BOJ]17406. 배열 돌리기 4  (0) 2021.09.08
[BOJ]2638. 치즈  (0) 2021.09.06
[BOJ]2636. 치즈  (0) 2021.09.03

2019/02/25 - [Algorithm/Python] - [Programmers]:Lv 3. 예산

문제:

n 명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다.

처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 명만 심사를 할 수 있습니다. 가장 앞에 서 있는 사람은 비어 있는 심사대로 가서 심사를 받을 수 있습니다. 하지만 더 빨리 끝나는 심사대가 있으면 기다렸다가 그 곳으로 가서 심사를 받을 수도 있습니다.

모든 사람이 심사를 받는데 걸리는 시간을 최소로 하고 싶습니다.

입국심사를 기다리는 사람 수 n, 각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times가 매개변수로 주어질 때, 모든 사람이 심사를 받는데 걸리는 시간의 최솟값을 return 하도록 solution 함수를 작성해주세요.

풀이 방법:

이분탐색 문제이므로 이 문제도 예산 문제와 같이 심사를 다 받는 시간을 찍어보면 된다. 왼쪽 값을 0 우측 값을 times의 가장 큰 값에 n을 곱한 값으로 설정하고 이분 탐색을 진행해 나가면 된다. 중간에 n명을 통과를 할 수 있는 시간이 있더라도 최소값을 찾기 위해 끝까지 진행해본다.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def solution(n, times):
    left=0
    right=max(times)*n
    temp=right
    answer=right
    while(right>=left):
        mid=(right+left)//2
        people=0
        for i in times:
            people+=mid//i
        if people==n:
            if answer>=mid:
                answer=mid
            right=mid-1
        elif people>n:
            right=mid-1
        else:
            left=mid+1
    if answer==temp:
        return right+1
    else:
        return answer
cs


+ Recent posts