본문 바로가기

Programming/BOJ277

[C/C++] 백준 #1655 가운데를 말해요(힙) 이번 문제는 구간의 중간수 구하던 문제와 같이 두개의 힙을 이용해서 풀 수 있는 문제입니다. 왼쪽은 최대힙(max heap)을 오른쪽은 최소힙(min heap)을 운영합니다. 왼쪽 힙은 오른쪽 힙의 개수보다 1개 크거나 같아야 합니다. 1, 5, 2, 10, -99, 7, 5 순으로 숫자가 불리었고, 이번에 10이 불리는 차례였다면, 왼쪽의 최대힙은 [ 2, 1 ] 이 들어가 있고, 오른쪽 최소힙은 [5]가 들어가 있습니다. 10을 왼쪽힙의 최대값 2와 비교해서 작으면 왼쪽에, 크면 오른쪽에 넣습니다. 이 경우엔 2보다 큰 수이므로 오른쪽에 들어가 있게 됩니다. 그러면 [ 2, 1 ]과 [ 5, 10 ] 이 되고, 두 힙의 크기가 같으니, 힙간 원소 이동은 없습니다. 왼쪽힙의 가장 큰 값을 출력하면 2가.. 2022. 9. 22.
[C/C++] 백준 #1654 랜선 자르기(이분 탐색) 랜선 자르기 문제는 K개의 랜선이 있을 때, 이 랜선을 적절히 잘라서 같은 길이의 N개의 랜선을 만드는 것입니다. 이 때, 가장 긴 길이의 N개의 랜선을 얻고자 할 때, 그 길이를 출력하는 것입니다. 이런 최적화 문제는 길이가 주어지면, K개의 랜선에서 N개의 랜선을 만들 수 있는지 검사하는 것은 어렵지 않다는 것입니다. 그리고 \( a \lt b \)를 만족하는 경우 b 길이가 가능하면 a 길이도 가능해야 문제를 풀 수 있습니다. 역으로 a 길이가 불가능하면 b 길이도 불가능해야 합니다. 그래야 이분 탐색을 이용하여 문제를 풀 수 있습니다. 4개의 랜선이 각각 길이가 802, 743, 457, 539 길이로 주어져있고, 이것으로 같은 길이의 11개 랜선을 요구한다고 합니다. \( K \le N \)이므.. 2022. 9. 22.
백준 #1648 격자판 채우기(동적 계획법) 이번 문제는 플래티넘으로 등급이 매겨진 문제입니다. 격자판의 크기가 주어지면, 2x1 미노로 격자판을 채우는 것입니다. 빈 곳이 있으면 안되고, 꽉 채우는 경우의 수를 계산하는 프로그램입니다. 일견 어려워보일 수 있겠지만, 동적 계획법을 잘 사용하면 쉽게 풀 수 있습니다. 2x1 미노를 세로 또는 가로로 채우는 문제이기 때문에 한줄을 다 채웠을 경우 다음줄에는 말끔하지 않게 되어 있을 수가 있습니다. 예를 들어서 3x6 격자판을 채운다고 해보죠. 첫줄을 채우는 방법은 다음의 두가지입니다. 두번째 줄의 모양에 따라서 안 채워진 곳은 0, 채워진 곳은 1이라고 한다면, 위의 두 패턴은 001과 100이 됩니다. 초기 패턴은 000이라고 할 수 있습니다. 그러면 우리는 점화식으로 다음과 같이 놓을 수 있습니다.. 2022. 9. 21.
[C/C++] 백준 #1647 도시 분할 계획(크루스칼 알고리즘) 이번 문제는 전형적인 최소 스패닝 트리(Minimum Spanning Tree) 문제입니다. 최소 스패닝 트리를 구하는 방법중 대표적인 방법은 프림(Prim) 알고리즘과 크루스칼(Kruskal) 알고리즘이 있습니다. 둘 중에 어떤 알고리즘이 좋은가를 할 때에는 제 개인적으로는 크루스칼 알고리즘이 더 좋습니다. 알고리즘 효율은 프림 알고리즘은 \(O(E \log E)\)이고 크루스칼 알고리즘은 \(O(E \log E)\) 로 비슷합니다. 물론 우선순위큐를 잘 만들면 프림 알고리즘은 \(O(E \log V)\) 까지도 가능하지만, 사실상 의미가 없습니다. \(E\) 자체의 최대치가 \(V(V-1)/2\) 이므로 로그(log) 함수 안에서는 아무런 의미가 없습니다. 개인적으로 크루스칼 알고리즘을 더 선호하는 .. 2022. 9. 20.
[C/C++] 백준 #1646 피이보나치 트리(동적 계획법) 피이보나치 트리 문제는 일견 어려워보일 수 있지만, 조성 방법이 정해져 있기 때문에, 그것을 이용해서 푸시면 됩니다. 정답자가 현재 90명정도로 적은 편의 문제입니다. 구현 자체가 어려워서라기보다는 문제 자체가 어려워서인 듯 합니다. N이 주어졌을 때, 루트는 최고층(가장 높은 레이어)에 위치하며 가장 먼 노드까지는 N-1번이면 도착하게 됩니다. 왼쪽 트리는 N-2에 대한 루트이고, 오른쪽 트리는 N-1에 대한 트리입니다. 이것을 이용하면 전체 트리에 대한 노드의 갯수 \(ft_N\)을 구할 수 있습니다. \[ ft_0 = 1, ~ ft_1 = 1 \] \[ ft_n = ft_{n-2} + ft_{n-1} + 1 \] 위의 점화식을 이용하면 우리는 손쉽게 노드의 갯수를 구할 수가 있습니다. 이제 이것을 .. 2022. 9. 18.
[C/C++] 백준 #1644 소수의 연속합(수학) 이번 문제는 연속된 소수들의 합을 이 주어진 값으로 표현되면, 그러한 경우의 수를 계산하는 것입니다. 원래는 소수들의 누적합을 이용해서 푸는 것이 좋겠죠. 먼저 n보다 작거나 같은 소수들의 집합을 구합니다. n이 30이라고 한다면 아래와 같은 소수들 리스트를 얻게 됩니다. 2 3 5 7 11 13 17 19 23 29 누적합은 다음과 같이 구할 수 있습니다. 우리는 이 누적합 테이블만 사용하면 됩니다. 2 5 10 17 28 41 58 77 80 109 이 누적합 테이블은 실제 연속된 합을 계산할 때 사용합니다. 제일 먼저 이분탐색을 이용해서 30을 찾습니다. 해당 값은 첫 소수부터 연속된 소수의 합이 30이 되는 경우입니다. 맨 처음 누적합에 0을 넣는다면 이 부분을 생략해도 됩니다. 이제 109부터 .. 2022. 9. 17.
728x90