문제 풀이

4월의 문제 풀이 - (1)

khj20006 2024. 4. 13. 06:30

 

 

너무 오래 쉰 것 같다.

종강을 하고도 PS는 종종 했지만, 글 쓰는게 귀찮아서 방치하다가 4개월치나 밀려버렸다.

 

한 번에 쓰기에는 문제 수가 너무 많아서 4월부터 다시 시작하려 한다...

 


4/2

BOJ 4384 - 공평하게 팀 나누기

Gold 1

더보기

#knapsack   #dp

 

모든 사람들의 몸무게 합은 $45\,000$ 이하이고, 사람의 수가 $100$명 이하이다.

따라서, 사람이 한 명씩 추가될 때마다 (몸무게 합, 사람 수)로 가능한 경우를 knapsack dp로 갱신해주면 된다.

 

BOJ 1043 - 거짓말

Gold 4

더보기

#bfs

 

주어진 $M$개의 파티 정보로 양방향 그래프를 만들고, 진실을 아는 사람들을 시작점으로 한 뒤 bfs를 돌려주자.

bfs 수행 중에 만나는 모든 사람들에게는 거짓말을 할 수 없다.

 

BOJ 31724 - Hyper Tree Problem

Platinum 4

더보기

#bitmask   #disjoint_set   #tree

 

문제를 살짝 변형해서, 가중치 값이 $0$ 또는 $1$인 경우에 대해서만 생각해보자.

2번 쿼리에서 $n$과 어떤 점 $i$에 대해 $dist(n,i)$는 트리 상에서 $n$ ~ $i$ 경로에 가중치 $1$인 간선이 존재하면 $1$, 아니면 $0$이다.

$n$을 트리의 루트로 보면, $n$에서 탐색을 시작하며 가중치 $1$인 간선을 만나는 순간, 해당 정점에서의 서브트리에 속하는 모든 점들과의 $dist$는 $1$이 된다.

따라서, $n$과의 $dist$가 $0$인 점들의 개수만 알면 $\sum \limits_{i=1}^{N} dist(n,i)$ 또한 알 수 있다.

분리 집합을 이용해 가중치 $0$인 간선에 대해 두 정점을 한 집합으로 합쳐주며 관리하면 된다.

또, bitwise연산은 정수를 이진수로 나타내었을 때 각 비트에 대해 독립적이기 때문에 모든 비트들에 대해 트리를 만들어주면 된다.

 

BOJ 31723 - 무빙워크

Platinum 5

더보기

#dijkstra

 

주어지는 방향 간선 $(u,v,d)$에 대해 반대 방향 간선 $(v,u,2d)$를 추가해주고 다익스트라를 수행하면 된다.

다른 모든 건물에 대한 최단 도달 시간의 합을 최소화한다는 말은 곧 모든 건물로의 최단 시간을 최소화시켜야 한다는 것이므로 그냥 다익스트라를 돌려주면 된다.

반대 방향 간선을 타는 일이 생기면 해당 간선에 대한 답을 $0$으로 바꿔주기만 하면 된다.

어떤 간선 $(u, v)$를 타는 최단 경로가 있으면 $(v, u)$를 타는 최단 경로는 없기 때문이다.


4/4

BOJ 7511 - 소셜 네트워킹 어플리케이션

Gold 5

더보기

#disjoint_set

 

분리 집합을 굳이 안 써도 되지만, 쓰면 구현이 편해진다.

 

BOJ 16965 - 구간과 쿼리

Gold 5

더보기

#bfs

 

구간을 정점으로 보고, 구간끼리의 이동 가능 여부를 간선으로 보는 그래프를 관리하면 된다.

2번 쿼리는 bfs로 처리하자. 제한이 작아서 충분히 시간 내에 들어온다.

 

BOJ 24517 - 카드 게임과 쿼리

Platinum 4

더보기

#bitmask_dp   #game   #math

 

$K$개의 카드를 모두 사용하는 경우를 $1$회 순환했다고 말할 수 있다.

$B-A \ge \dfrac{K(K+1)}{2}$인 경우에는 $s$회 순환하면 항상 $B-A < \dfrac{K(K+1)}{2}$인 경우로 만들어줄 수 있다.

$K$와 $s$가 모두 홀수이면 선공이 바뀜에 유의해야 한다.

이제 게임에는 $K \times 2^{K}$ 가지 경우만 존재할 수 있고, bitmask dp로 처리해주면 된다.

$Q$번의 쿼리마다 직접 수행하면 시간 초과이므로 미리 모든 경우를 전처리해주면 된다.

 

BOJ 28083 - 마왕의 성

Platinum 5

더보기

#disjoint_set   #sorting

 

높이가 가장 낮은 땅부터 보면서, 인접한 칸들 중 더 작은 칸들이 있다면 분리 집합으로 합쳐주면 된다.

비슷한 난이도를 가진 유사한 문제가 많이 있다.

 

BOJ 30651 - AN2DL

Platinum 3

더보기

#priority_queue

 

행, 열을 따로 압축해주면 된다.

각각의 압축은 (원소, 인덱스)를 관리하는 우선순위 큐로 진행하면 된다.

 

BOJ 2849 - 탭댄스

Platinum 1

더보기

#segtree

 

연속합과 쿼리의 응용 버전이다.

원하는 결과를 얻을 수 있도록, 세그트리의 각 노드에 필요한 값을 모두 가지고 있으면서 잘 합쳐주면 된다.

 

BOJ 8741 - 이진수 합

Bronze 2

더보기

#math

 

$n$개의 $1$, $n-1$개의 $0$을 출력하면 된다.

 

BOJ 23061 - 백남이의 여행 준비

Gold 3

더보기

#knapsack   #dp

 

knapsack dp로 $dp[i]$를 구해주고, 각 $K_i$마다 $\dfrac{\max(dp[1], \cdots, dp[K_i])}{K_i}$를 구해주면 된다.

 

BOJ 11402 - 이항 계수 4

Platinum 4

더보기

#lucas'_theorem   #combinatorics

 

뤼카 정리의 기본 문제이다.

쿼리 형식의 문제였으면 DP로 $O(M^2)$에 combination 값을 전처리해야 하지만, 그게 아니기 때문에 매번 직접 계산해줘도 된다.


4/8

BOJ 14863 - 서울에서 경산까지

Gold 4

더보기

#knapsack   #dp

 

$O(NK)$ knapsack으로 해결할 수 있다.

 

BOJ 31669 - 특별한 학교 탈출

Bronze 3

더보기

#implementation

 

'X'만 존재하는 열 중 가장 번호가 작은 걸 출력하면 된다.

 

BOJ 27437 - 분수찾기 2

Silver 1

더보기

#math   #binary_search

 

$X$가 몇 번째 대각선에 속해있는지를 이분 탐색으로 찾고, parity에 따라 맞는 값을 출력해주면 된다.

 

BOJ 4276 - 0이 몇 개?

Gold 2

더보기

#math

 

$F(n)$을 $0$부터 $n$까지 $0$이 등장하는 횟수라 정의하고, 각 자릿수별로 $0$이 몇 번 등장하는지를 모두 합쳐주면 $F(n)$을 구할 수 있다.

$F(m) - F(n-1)$을 구하면 된다.


4/9

BOJ 15777 - Xtreme NP-hard Problem?!

Diamond 4

더보기

#mitm   #case_work   #graph

 

$n$ 혹은 $m$이 $5$ 이하인 경우에는 가능한 경로를 어떻게든 모두 구하면 된다. (본인은 재귀 람다식으로 구현했다.)

$k$가 $5$ 이하인 경우는 if문 다섯 개로 나눠서 각각 따로 처리해주었다.

$k = 1$일 때는 $(1, n)$간선, $k=2$일 때는 $(1,p)$와 $(p,n)$간선에 대해 확인해주었다.

$k \ge 3$일 때는 $1$, $n$ 각각에서 뻗는 길이 $2$이하인 경로들을 적절히 합쳐주며 구했다.

경로 두 개를 합칠 때, 중복되는 정점이 없도록 최솟값의 후보들을 여러 개 관리해야 해서 구현이 힘들었다.

 

BOJ 1937 - 욕심쟁이 판다

Gold 3

더보기

#dp   #sorting

 

최솟값부터 보면서 dp테이블을 구성해주었다.

어떤 점 $(x,y)$에서의 $dp[x][y]$는 인접한 네 방향의 max dp값 + 1이 된다.


4/10

BOJ 14222 - 배열과 연산

Gold 5

더보기

#greedy

 

counting 배열을 만들고, $1$부터 $N$까지 보면서 $cnt[i] > 1$인 $i$에 대해 $cnt[i] = 1$이 될 때까지 $pK + i$꼴로 바꿔주면 된다.

이렇게 했을 때 $1$ ~ $N$이 모두 만들어지지 않으면 불가능하다.

 

BOJ 9167 - 도발 봇

Platinum 5

더보기

#implementation   #parsing   #recursion

 

그냥 문제에서 주어진 BNF를 통째로 재귀로 구현하면 된다.

본인은 평소에 코드를 작성하는 속도가 느리지 않다고 생각하는데도, 생각 20분에 구현이 40분이나 걸렸다.


.

.

.

앞으로 열심히 쓰겠습니다..

'문제 풀이' 카테고리의 다른 글

4월의 문제 풀이 - (3)  (0) 2024.05.01
4월의 문제 풀이 - (2)  (0) 2024.04.22
BOJ 1176 - 섞기 [C++]  (0) 2023.12.14
BOJ 24502 - blobsad [C++]  (0) 2023.12.12
BOJ 9015 - 정사각형 [C++]  (0) 2023.12.12