문제

 

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

 

5639번: 이진 검색 트리

트리를 전위 순회한 결과가 주어진다. 노드에 들어있는 키의 값은 106보다 작은 양의 정수이다. 모든 값은 한 줄에 하나씩 주어지며, 노드의 수는 10,000개 이하이다. 같은 키를 가지는 노드는 없다

www.acmicpc.net

이진 검색 트리는 다음과 같은 세 가지 조건을 만족하는 이진 트리이다.

  • 노드의 왼쪽 서브트리에 있는 모든 노드의 키는 노드의 키보다 작다.
  • 노드의 오른쪽 서브트리에 있는 모든 노드의 키는 노드의 키보다 크다.
  • 왼쪽, 오른쪽 서브트리도 이진 검색 트리이다.

전위 순회 (루트-왼쪽-오른쪽)은 루트를 방문하고, 왼쪽 서브트리, 오른쪽 서브 트리를 순서대로 방문하면서 노드의 키를 출력한다. 후위 순회 (왼쪽-오른쪽-루트)는 왼쪽 서브트리, 오른쪽 서브트리, 루트 노드 순서대로 키를 출력한다. 예를 들어, 위의 이진 검색 트리의 전위 순회 결과는 50 30 24 5 28 45 98 52 60 이고, 후위 순회 결과는 5 28 24 45 30 60 52 98 50 이다.

이진 검색 트리를 전위 순회한 결과가 주어졌을 때, 이 트리를 후위 순회한 결과를 구하는 프로그램을 작성하시오.

 

입력

트리를 전위 순회한 결과가 주어진다. 노드에 들어있는 키의 값은 106보다 작은 양의 정수이다. 모든 값은 한 줄에 하나씩 주어지며, 노드의 수는 10,000개 이하이다. 같은 키를 가지는 노드는 없다.

 

출력

입력으로 주어진 이진 검색 트리를 후위 순회한 결과를 한 줄에 하나씩 출력한다.

 

예제

입력 출력
50
30
24
5
28
45
98
52
60
5
28
24
45
30
60
52
98
50

 

문제풀이 코드

# 시간초과
class TreeNode:
    def __init__(self, val = 0, left = None, right = None):
        self.val = val
        self.left = left
        self.right = right

class BST:
    def __init__(self, head):
        self.head = head

    def insert(self, value):
        self.current = self.head
        while True:
            if value < self.current.val:
                if self.current.left != None:
                    self.current = self.current.left
                else:
                    self.current.left = TreeNode(value)
                    break
            else:
                if self.current.right != None:
                    self.current = self.current.right
                else:
                    self.current.right = TreeNode(value)
                    break

    def postOrder(self, node):
        if node == None:
            return
    
        self.postOrder(node.left)

        self.postOrder(node.right)

        print(node.val)
    
    
lst = []
while True:
    try:
        lst.append(int(input()))
    except:
        break

bst = BST(TreeNode(lst[0]))

for i in range(1, len(lst)):
    bst.insert(lst[i])

bst.postOrder(bst.head)

트리를 생성하고 탐색하는 방식으로 접근

1. 전위순회된 결과를통해 이진 검색 트리를 생성한다.

2. 생성된 이진 검색 트리를 후위순회하여 결과를 반환한다

** 시간초과로 통과하지 못했다..

 

 

import sys
sys.setrecursionlimit(1000000)

lst = []
while True:
    try:
        lst.append(int(input()))
    except:
        break

def postorder(start,end):
    if start > end:
        return
    mid = end+1  
    for i in range(start+1,end+1):
        if lst[start] < lst[i]:
            mid = i
            break
    
    postorder(start+1, mid-1)
    postorder(mid, end)
    print(lst[start])

postorder(0,len(lst)-1)

다른 사람 코드를 참고해서 문제 풀이

이진 탐색 트리기때문에 주어진 배열에서 현재 값보다 큰 값을 마주칠때부터 현재 노드의 오른쪽 노드가 된다.

현재 값보다 큰 값을 만났을 때 mid를 i값으로 바꿔준다.(i - 1까지가 현재 노드의 left노드)

[start + 1:mid -1] 이 현재 노드의 left노드이고

[mid:end]는 현재 노드의 right노드이다

이 과정을 재귀적으로 반복하면서 트리를 새로 구성하지않고 주어진 트리를 후위순회할 수 있다.

 

예제 해결 과정

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 4181.Convex Hull  (0) 2022.11.27
[백준] 1238.파티  (0) 2022.10.25
[백준] 7576.토마토  (0) 2022.10.10
[백준] 11404.플로이드  (0) 2022.10.09
[백준] 4963.섬의 개수  (0) 2022.10.09

문제

 

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

 

7576번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토

www.acmicpc.net

철수의 토마토 농장에서는 토마토를 보관하는 큰 창고를 가지고 있다. 토마토는 아래의 그림과 같이 격자 모양 상자의 칸에 하나씩 넣어서 창고에 보관한다. 

창고에 보관되는 토마토들 중에는 잘 익은 것도 있지만, 아직 익지 않은 토마토들도 있을 수 있다. 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다. 하나의 토마토의 인접한 곳은 왼쪽, 오른쪽, 앞, 뒤 네 방향에 있는 토마토를 의미한다. 대각선 방향에 있는 토마토들에게는 영향을 주지 못하며, 토마토가 혼자 저절로 익는 경우는 없다고 가정한다. 철수는 창고에 보관된 토마토들이 며칠이 지나면 다 익게 되는지, 그 최소 일수를 알고 싶어 한다.

토마토를 창고에 보관하는 격자모양의 상자들의 크기와 익은 토마토들과 익지 않은 토마토들의 정보가 주어졌을 때, 며칠이 지나면 토마토들이 모두 익는지, 그 최소 일수를 구하는 프로그램을 작성하라. 단, 상자의 일부 칸에는 토마토가 들어있지 않을 수도 있다.

 

입력

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 상자에 담긴 토마토의 정보가 주어진다. 하나의 줄에는 상자 가로줄에 들어있는 토마토의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0은 익지 않은 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다.

토마토가 하나 이상 있는 경우만 입력으로 주어진다.

 

출력

여러분은 토마토가 모두 익을 때까지의 최소 날짜를 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

 

예제1

입력 출력
6 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
8

 

예제2

입력 출력
6 4
0 -1 0 0 0 0
-1 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
-1
 

 

문제풀이 코드

from collections import deque
import queue
M, N = map(int, input().split())

tomato = [list(map(int, input().split())) for _ in range(N)]

dx, dy = [0, 1, 0, -1] , [1, 0, -1, 0]

result = 0
dq = deque()

for i in range(N):
    for j in range(M):
        if tomato[i][j] == 1:
            dq.append([i, j])

while dq:
    x, y = dq.popleft()
    for i in range(4):
        xx, yy = dx[i] + x, dy[i] + y
        if 0 <= xx < N and 0 <= yy < M and tomato[xx][yy] == 0:
            tomato[xx][yy] = tomato[x][y] + 1
            dq.append([xx, yy])


for t in tomato:
    if 0 in t:
        print(-1)
        exit(0)
    result = max(result, max(t))

print(result - 1)

dfs로 접근했다가 문제가 해결되지않아 bfs로 문제 접근

1. 처음에 익어있는 토마토의 위치를 queue에 삽입해준다.

2. 해당 queue로 bfs를 돌린다.

3. 주변 토마토가 0일때만 현재 위치의 값 + 1을 대입해주고 큐에 현재 좌표를 넣어준다.

4. 반복문이 종료되고 tomato에 0값이 존재하면 익지않은 토마토가 있는거니 -1을출력

5. 아니면 tomato배열에서 가장 큰 값에 -1을 뺀 값을 출력한다.(1부터 시작했기때문에 1을 빼줘야함)

 

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 1238.파티  (0) 2022.10.25
[백준] 5639.이진 검색 트리  (0) 2022.10.14
[백준] 11404.플로이드  (0) 2022.10.09
[백준] 4963.섬의 개수  (0) 2022.10.09
[백준] 2267.단지번호붙이기  (2) 2022.10.04

 

문제

 

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

 

11404번: 플로이드

첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가

www.acmicpc.net

n(2 ≤ n ≤ 100)개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 m(1 ≤ m ≤ 100,000)개의 버스가 있다. 각 버스는 한 번 사용할 때 필요한 비용이 있다.

모든 도시의 쌍 (A, B)에 대해서 도시 A에서 B로 가는데 필요한 비용의 최솟값을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 버스의 정보는 버스의 시작 도시 a, 도착 도시 b, 한 번 타는데 필요한 비용 c로 이루어져 있다. 시작 도시와 도착 도시가 같은 경우는 없다. 비용은 100,000보다 작거나 같은 자연수이다.

시작 도시와 도착 도시를 연결하는 노선은 하나가 아닐 수 있다.

 

출력

n개의 줄을 출력해야 한다. i번째 줄에 출력하는 j번째 숫자는 도시 i에서 j로 가는데 필요한 최소 비용이다. 만약, i에서 j로 갈 수 없는 경우에는 그 자리에 0을 출력한다.

 

예제

입력 출력
5
14
1 2 2
1 3 3
1 4 1
1 5 10
2 4 2
3 4 1
3 5 1
4 5 3
3 5 10
3 1 8
1 4 2
5 1 7
3 4 2
5 2 4
0 2 3 1 4
12 0 15 2 5
8 5 0 1 1
10 7 13 0 3
7 4 10 6 0

 

문제풀이 코드

N = int(input())
M = int(input())

distance = [[float('inf')] * N for _ in range(N)]

for _ in range(M):
    start, end, dist = map(int, input().split())
    distance[start-1][end-1] = min(distance[start-1][end-1], dist)

for k in range(N):
    for i in range(N):
        for j in range(N):
            if i == j:
                distance[i][j] = 0
            else: distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j])
for i in range(N):
    for j in range(N):
        if distance[i][j] == float('inf'):
            distance[i][j] = 0
        print(distance[i][j], end=' ')
    print()

플로이드-워셜 알고리즘으로 문제 풀이(참조: 플로이드-워셜)

1. 플로이드-워셜 알고리즘의 기본 문제로 이동 가능한 모든 노드를 탐색하며 최단거리를 구한다.

2. 해당 알고리즘을 통해 나온 거리가 곧 정답이 된다.

 

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 5639.이진 검색 트리  (0) 2022.10.14
[백준] 7576.토마토  (0) 2022.10.10
[백준] 4963.섬의 개수  (0) 2022.10.09
[백준] 2267.단지번호붙이기  (2) 2022.10.04
[백준] 2187.미로 탐색  (0) 2022.10.02

문제

 

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

 

4963번: 섬의 개수

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다. 둘째 줄부터 h개 줄에는 지도

www.acmicpc.net

정사각형으로 이루어져 있는 섬과 바다 지도가 주어진다. 섬의 개수를 세는 프로그램을 작성하시오.

한 정사각형과 가로, 세로 또는 대각선으로 연결되어 있는 사각형은 걸어갈 수 있는 사각형이다. 

두 정사각형이 같은 섬에 있으려면, 한 정사각형에서 다른 정사각형으로 걸어서 갈 수 있는 경로가 있어야 한다. 지도는 바다로 둘러싸여 있으며, 지도 밖으로 나갈 수 없다.

 

입력

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다.

둘째 줄부터 h개 줄에는 지도가 주어진다. 1은 땅, 0은 바다이다.

입력의 마지막 줄에는 0이 두 개 주어진다.

 

출력

각 테스트 케이스에 대해서, 섬의 개수를 출력한다.

 

예제

입력 출력
1 1
0
2 2
0 1
1 0
3 2
1 1 1
1 1 1
5 4
1 0 1 0 0
1 0 0 0 0
1 0 1 0 1
1 0 0 1 0
5 4
1 1 1 0 1
1 0 1 0 1
1 0 1 0 1
1 0 1 1 1
5 5
1 0 1 0 1
0 0 0 0 0
1 0 1 0 1
0 0 0 0 0
1 0 1 0 1
0 0
0
1
1
3
1
9

 

문제풀이 코드

import sys
sys.setrecursionlimit(1000000)

graph = []
dx, dy = [0, 1, 0, -1, -1, -1, +1, +1], [1, 0, -1, 0, -1, +1, +1, -1]

def dfs(x, y):
    graph[x][y] = 0

    for i in range(8):
        xx, yy = dx[i] + x, dy[i] + y
        if xx <= -1 or xx >= len(graph) or yy <= -1 or yy >= len(graph[0]) or graph[xx][yy] == 0:
            continue
        dfs(xx, yy)

while True:
    w, h = map(int, input().split())
    answer = 0
    if w == 0 and h == 0:
        break
    
    graph = [list(map(int, input().split())) for _ in range(h)]
    for i in range(len(graph)):
        for j in range(len(graph[0])):
            if graph[i][j] == 1:
                answer += 1
                dfs(i, j)
    print(answer)

1. 문제를 확인해보면 상하좌우뿐 아니라 해당 노드의 위치에서 대각선까지 포함하기때문에 dx, dy에 대각선에대한 좌표도 추가해준다.

2. 반복문을 돌면서 배열에서 1을 만났을 때 dfs함수를 호출한다.

3. dfs함수는 1을 만났을 때 현재 노드에 이어진 모든 노드를 0으로 초기화한다.

4. 반복문이 종료되면 answer의 값이 총 섬의 개수가 된다.

 

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 7576.토마토  (0) 2022.10.10
[백준] 11404.플로이드  (0) 2022.10.09
[백준] 2267.단지번호붙이기  (2) 2022.10.04
[백준] 2187.미로 탐색  (0) 2022.10.02
[백준] 11053. 가장 긴 증가하는 부분 수열  (0) 2022.09.27

문제

 

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

 

2667번: 단지번호붙이기

<그림 1>과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여

www.acmicpc.net

<그림 1>과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여기서 연결되었다는 것은 어떤 집이 좌우, 혹은 아래위로 다른 집이 있는 경우를 말한다. 대각선상에 집이 있는 경우는 연결된 것이 아니다. <그림 2>는 <그림 1>을 단지별로 번호를 붙인 것이다. 지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수를 오름차순으로 정렬하여 출력하는 프로그램을 작성하시오.

입력

첫 번째 줄에는 지도의 크기 N(정사각형이므로 가로와 세로의 크기는 같으며 5≤N≤25)이 입력되고, 그 다음 N줄에는 각각 N개의 자료(0혹은 1)가 입력된다.

출력

첫 번째 줄에는 총 단지수를 출력하시오. 그리고 각 단지내 집의 수를 오름차순으로 정렬하여 한 줄에 하나씩 출력하시오.

예제

입력 출력
7
0110100
0110101
1110101
0000111
0100000
0111110
0111000
3
7
8
9

 

문제풀이 코드

N = int(input())

graph = [list(input()) for _ in range(N)]

dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
comp = 0
house_count = []

# 단지 내 집의 수 카운트 
def dfs(x, y):
    graph[x][y] = '0'
    ret = 1
    for i in range(4):
        xx, yy = dx[i] + x, dy[i] + y
        if xx < 0 or xx >= N or yy < 0 or yy >= len(graph[0]) or graph[xx][yy] == '0':
            continue
        ret += dfs(xx, yy)
    return ret

for i in range(len(graph)):
    for j in range(len(graph[0])):
        if graph[i][j] == '1':
            comp += 1
            ret = dfs(i,j)
            house_count.append(ret)
print(comp)
for h in sorted(house_count):
    print(h)

dfs를 이용하여 문제 풀이

1. dfs가 호출될 때 마다 comp += 1을 해준다 -> dfs가 호출되는 수가 단지의 수

2. dfs함수가 1을 만났을 때는 ret += dfs(xx, yy) -> dfs가 재귀적으로 실행되는 수가 단지 내 집의 수

3. 위 두가지 수를 새어 반환하면 된다.

 

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 11404.플로이드  (0) 2022.10.09
[백준] 4963.섬의 개수  (0) 2022.10.09
[백준] 2187.미로 탐색  (0) 2022.10.02
[백준] 11053. 가장 긴 증가하는 부분 수열  (0) 2022.09.27
[백준] 1931. 회의실 배정  (2) 2022.09.25

문제

 

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

 

2178번: 미로 탐색

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

www.acmicpc.net

 
 

N×M크기의 배열로 표현되는 미로가 있다.

1 0 1 1 1 1
1 0 1 0 1 0
1 0 1 0 1 1
1 1 1 0 1 1

미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.

위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.

 

입력

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

출력

첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.

예제

입력 출력
4 6
101111
101010
101011
111011
15
 
 

문제풀이 코드

from collections import deque

def bfs(graph):
    dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
    distance = [[-1 for _ in range(len(graph[0]))] for _ in range(len(graph))]
    distance[0][0] = 1

    queue = deque()
    queue.append((0,0))

    while queue:
        x, y = queue.popleft()
        for i in range(4):
            xx, yy = dx[i] + x, dy[i] + y
            if xx >= 0 and xx < len(graph) and yy >= 0 and yy < len(graph[0]):
                if distance[xx][yy] == -1 and graph[xx][yy] == '1':
                    distance[xx][yy] = distance[x][y] + 1
                    queue.append((xx, yy))
    return distance


N, M = map(int, input().split())

graph = [list(input()) for _ in range(N)]

distance = bfs(graph)
print(distance[N-1][M-1])

1. bfs를 이용한 문제풀이

2. 큐에 첫 출발인 0,0을 삽입한 상태로 루프를 돈다.

3. xx, yy가 그래프의 범위를 벗어나지 않고, distance[xx][yy]를 방문한적이 없고, graph[xx][yy]가 갈 수있는 길이라면

4. distance[xx][yy] =  현재위치의 값 + 1이 된다.

5. 그리고 xx, yy좌표를 큐에 넣어주고 루프가 끝날 때 탐색한 거리를 반환해준다.

6. 거리의 마지막 지점을 리턴해주면 끝

 

 

문제

 

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

 

11053번: 가장 긴 증가하는 부분 수열

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이

www.acmicpc.net

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

 

예제

입력 출력
6
10 20 10 30 20 50
4
 
 

문제풀이 코드

첫번째 풀이(다이나믹 프로그래밍)

N = int(input())

lst = list(map(int, input().split()))
dp = [1 for _ in range(1001)]

for i in range(len(lst)):
    for j in range(i):
        if lst[i] > lst[j]:
            dp[i] = max(dp[i], dp[j] + 1)
print(max(dp))

1. 가장 앞에서부터 i번째 까지 루프를 돌며 lst[i]값이 lst[j]값보다 클 때 dp값 변경

2. dp값은 dp[i]나 dp[j]+1중 큰 값으로 초기화해준다.

3. dp에서 가장 큰 값이 가장 긴 수열의 길이가 된다.

 

두번째 풀이(이분탐색)

N = int(input())

lst = list(map(int, input().split()))
answer = []


def binary_search(start, end, num):
    while start < end:
        mid = (start + end) // 2
        if answer[mid] < num:
            start = mid + 1
        else:
            end = mid 
    return start

answer.append(lst.pop(0))

while lst:
    num = lst.pop(0)
    if num > answer[-1]:
        answer.append(num)
    else:
        idx = binary_search(0, len(answer) - 1, num)
        answer[idx] = num
print(len(answer))

lowerbound(이분탐색)을 이용한 풀이

1. answer리스트의 마지막 값을 확인하여 해당 값이 크면 answer에 삽입해주고 그렇지 않으면

2. answer리스트를 이분탐색하며 해당 값보다 작은 값의 다음 인덱스를 찾아온다.

3. 현재 num은 인덱스 값보단 작고 이분탐색된 값보단 크기때문에 찾아온 인덱스에 현재값을 대입해준다.

4. 결과값은 answer의 길이가 됨

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 2267.단지번호붙이기  (2) 2022.10.04
[백준] 2187.미로 탐색  (0) 2022.10.02
[백준] 1931. 회의실 배정  (2) 2022.09.25
[백준] 2579. 계단 오르기  (0) 2022.09.19
[백준] 1149. RGB거리  (0) 2022.09.18

문제

 

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

 

1931번: 회의실 배정

(1,4), (5,7), (8,11), (12,14) 를 이용할 수 있다.

www.acmicpc.net

 

한 개의 회의실이 있는데 이를 사용하고자 하는 N개의 회의에 대하여 회의실 사용표를 만들려고 한다. 각 회의 I에 대해 시작시간과 끝나는 시간이 주어져 있고, 각 회의가 겹치지 않게 하면서 회의실을 사용할 수 있는 회의의 최대 개수를 찾아보자. 단, 회의는 한번 시작하면 중간에 중단될 수 없으며 한 회의가 끝나는 것과 동시에 다음 회의가 시작될 수 있다. 회의의 시작시간과 끝나는 시간이 같을 수도 있다. 이 경우에는 시작하자마자 끝나는 것으로 생각하면 된다.

입력

첫째 줄에 회의의 수 N(1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N+1 줄까지 각 회의의 정보가 주어지는데 이것은 공백을 사이에 두고 회의의 시작시간과 끝나는 시간이 주어진다. 시작 시간과 끝나는 시간은 231-1보다 작거나 같은 자연수 또는 0이다.

출력

첫째 줄에 최대 사용할 수 있는 회의의 최대 개수를 출력한다.

예제

입력 출력
11
1 4
3 5
0 6
5 7
3 8
5 9
6 10
8 11
8 12
2 13
12 14
4

 

문제풀이 코드

N = int(input())
lst = sorted([list(map(int, input().split())) for x in range(N)], key=lambda x:(x[1], x[0]))
answer = 1
end = lst[0][1]

for i in range(1, N):
    if lst[i][0] >= end:
        answer += 1
        end = lst[i][1]
print(answer)

회의가 빨리 종료될 수록 추가할 수 있는 회의가 많아짐

1. 회의 시간 리스트를 종료시간, 시작시간을 기준으로 정렬한다

2. 회의 시간 리스트의 원소를 차례로 비교하며 회의 시작 시간이 end보다 크거나 같을 때 회의의 갯수를 더해준다

'Problem Solving > 백준' 카테고리의 다른 글

[백준] 2187.미로 탐색  (0) 2022.10.02
[백준] 11053. 가장 긴 증가하는 부분 수열  (0) 2022.09.27
[백준] 2579. 계단 오르기  (0) 2022.09.19
[백준] 1149. RGB거리  (0) 2022.09.18
[백준] 1463. 1로 만들기  (0) 2022.09.17

+ Recent posts