JB의 이모저모

[BOJ 18353🥈2] 병사 배치하기 (Python) 본문

알고리즘/백준

[BOJ 18353🥈2] 병사 배치하기 (Python)

J B 2023. 10. 30. 13:02

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

 

18353번: 병사 배치하기

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 2,000) 둘째 줄에 각 병사의 전투력이 공백을 기준으로 구분되어 차례대로 주어진다. 각 병사의 전투력은 10,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

문제

N명의 병사가 무작위로 나열되어 있다. 각 병사는 특정한 값의 전투력을 보유하고 있으며, 병사를 배치할 때는 전투력이 높은 병사가 앞쪽에 오도록 내림차순으로 배치를 하고자 한다. 다시 말해 앞쪽에 있는 병사의 전투력이 항상 뒤쪽에 있는 병사보다 높아야 한다.

또한 배치 과정에서는 특정한 위치에 있는 병사를 열외시키는 방법을 이용한다. 그러면서도 남아있는 병사의 수가 최대가 되도록 하고 싶다.

예를 들어, N=7일 때 나열된 병사들의 전투력이 다음과 같다고 가정하자.

이 때 3번 병사와 6번 병사를 열외시키면, 다음과 같이 남아있는 병사의 수가 내림차순의 형태가 되며 5명이 된다. 이는 남아있는 병사의 수가 최대가 되도록 하는 방법이다.

병사에 대한 정보가 주어졌을 때, 남아있는 병사의 수가 최대가 되도록 하기 위해서 열외해야 하는 병사의 수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 2,000) 둘째 줄에 각 병사의 전투력이 공백을 기준으로 구분되어 차례대로 주어진다. 각 병사의 전투력은 10,000,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 남아있는 병사의 수가 최대가 되도록 하기 위해서 열외해야 하는 병사의 수를 출력한다.

예제 입력 1

7
15 11 4 8 5 2 4

예제 출력 1

2

 

⭕ CODE

from bisect import bisect_left

n = int(input())

arr = list(map(int,input().split()))
# 증가하는 부분수열을 찾기 위해 역순으로
new = list(reversed(arr))

d = []

d.append(new[0])

for i in range(n):
	# d의 마지막 값보다 크다면
    if new[i] > d[-1]:
    	# 증가하므로 추가
        d.append(new[i])
    # 더 작다면 
    else:
    	# 들어갈 인덱스를 구하고
        idx = bisect_left(d, new[i])
        # 그 인덱스를 바꿔준다
        d[idx] = new[i]

# 제거해야하는 수를 구해야 하므로 n에서 d의 길이만큼 빼준다
print(n-len(d))

✏️ Comment

문제를 읽어보면 가장 긴 감소하는 부분수열을 구하는 것이였다. 이를 bisect를 사용하여 문제를 해결하려고 하였지만 bisect는 오름차순으로 정렬된 경우에만 사용가능했다. 그래서 처음에 15 11 4 에서 8이 인덱스를 찾아가면 15 11 8을 원했지만 오름차순이기에 15앞에 들어가져서 역순으로 풀 생각을 하였다.