자료 구조 16

[백준 01321] 군인 [Java]

문제 캠프 내내 그랬듯이, 여전히 옆 나라와의 전쟁이 한창이다. 전쟁에는 N개의 부대가 투입되었는데, 전쟁이 장기전이 되다 보니 군사의 적절한 배치를 위해 각 부대에 군인이 늘어나기도 하고 줄어들기도 하고 있다. 행정의 편의를 위해 각 군인들에겐 번호가 붙어 있는데, 군인들은 1번 부대부터 군번순서대로 차례차례 배치된다. 예를 들어 1번 부대에 4명, 2번 부대에 3명, 3번 부대에 7명의 군인이 있다면 군번이 6번인 군인은 2번 부대에 배치되게 된다. 문제는 어떤 부대의 인원이 늘어나거나 줄어들었을 때 i번 군인이 어디에 배치되는지 인데, 이럴 때에는 군인도 군번도 처음부터 다시 배치하게 된다. 위의 예에서와 같이 1번 부대에 4명, 2번 부대에 3명, 3번 부대에 7명의 군인이 있었는데, 1번 부대에..

[백준 15678] 연세워터파크 [C++]

풀이 정수 K가 적혀있는 N개의 징검다리에 대해 징검다리를 건너며 얻을 수 있는 최대값을 구하는 문제다. 문제에서 주어진 조건 중 아래와 같은 조건이 있다. N개의 모든 징검다리에 순서대로 1 ~ N의 번호를 붙인다. U번 징검다리에서 V번 징검다리로 점프하기 위해서는, U와 V의 차이가 미리 정해진 값 D 이하여야 한다. 어떤 징검다리도 두 번 이상(한 번을 넘게) 밟을 수는 없다. 때문에, 징검다리의 양 끝이 아닌 중간에서 시작하더라도 왼쪽 또는 오른쪽 방향으로만 진행할 수 있다. 서로 다른 방향이더라도 결국 반대 방향의 부분집합에 속하는 영역이기 때문에 징검다리를 한 방향으로 진행한다고 가정하고 dp로 풀이할 수 있다. 진행 방향은 1번부터 N번이며 D씩 이동한다면 모든 징검다리가 탐색 대상이다. ..

[백준 2104] 부분배열 고르기 [C++]

풀이 일반적으로 범위가 넓을수록 최솟값과의 곱으로 인해 점수가 작을것이다. 때문에, 최솟값을 기준으로 나눈 영역(최솟값을 제외한 나머지 영역)에 대해 점수를 구할 때 높은 점수를 기대할 수 있다. 그러기 위해서는 먼저, 구간별로 가지는 합과, 최솟값을 구해야 한다. leaf를 입력받은 후 초기화를 진행해주자. pair에 합과, 최솟값을 가지는 요소의 index를 넣어줬다. 위에서 언급했듯, 최솟값을 기준으로 나눈 영역의 범위를 설정하기 위해서 value가 아닌 index를 넣어줬다. 구간별로 점수를 계산하기 위해 query를 작성해주었다. 주어진 구간에 대한 합과 최솟값의 index로 이루어진 pair를 반환한다. 초기화 단계에서는 올바르지 않은 요소를 접근하지 않는다. 하지만 위의 query는 올바르지..

[백준 1939] 중량제한 [Java]

풀이 출발지(from)와 목적지(to)에 대해 연결된 다리 중 최대중량을 구하는 문제다. 입력받은 다리의 중량제한에 대해 내림차순 정렬 후 순서대로 union시키며, from과 to가 동일한 집합에 속하는지(연결됬는지) 확인해주어 연결된 순간 union한 간선의 가중치가 최대 가중치이므로 출력하면 된다. 소스코드 소스코드 보기 출처 1939번: 중량제한 첫째 줄에 N, M(1 ≤ M ≤ 100,000)이 주어진다. 다음 M개의 줄에는 다리에 대한 정보를 나타내는 세 정수 A, B(1 ≤ A, B ≤ N), C(1 ≤ C ≤ 1,000,000,000)가 주어진다. 이는 A번 섬과 B번 섬 사이에 중량제한이 www.acmicpc.net

[백준 10775] 공항 [Java]

풀이 Greedy 순서대로 들어오는 비행기에 대해 최대한 많은 비행기를 매칭시켜야 한다. 만약 순서대로 들어오는 비행기 중 한대가 매칭이 불가능 하다면 공항이 폐쇄되기 때문에 탐색을 중단해야 한다. 그렇다면, 비행기를 최대로 매칭시키는 방법은 뭘까? 비행기는 1 ~ g 번째 게이트 중 어디든지 도킹하면 된다. 하지만, 최대한 많은 비행기를 도킹하기 위해서는 g번 게이트에 가깝게 비행기를 도킹함으로써 다른 비행기가 확률적으로 도킹을 하게될 낮은 번호를 피하는 방법이다. 위의 그림을 보면 모든 비행기가 1 ~ gi번 게이트라는 선택지가 주어졌기에 최대한 높은번호를 선택해야 많은 비행기가 도킹 가능하다. 그렇다면 어떻게 최대한 높은 번호의 게이트를 찾을까? 단순한 방법으로 gi부터 1번 게이트까지 이미 도킹중..

[백준 20040] 사이클 게임 [Java]

풀이 n개의 점에 대해 주어지는 m개의 선분이 사이클을 이루는지 확인하는 문제다. 쉽게 두 원소 x, y에 대해 union할 때 대표 원소가 동일하다면, 선형 구조상 동일한 집합에 속한 원소들이고 한 번 더 연결하려 시도했기 때문에 사이클을 형성할 것이다. 만약 union이 모두 정상적으로 이루어졌다면, 동일한 집합에 속한 원소들끼리 union이 이루어지지 않았기에 사이클은 생길 수 없다. 사이클이 생기지 않은 경우에는 0을 출력하면 된다. 소스코드 소스코드 보기 출처 20040번: 사이클 게임 사이클 게임은 두 명의 플레이어가 차례대로 돌아가며 진행하는 게임으로, 선 플레이어가 홀수 번째 차례를, 후 플레이어가 짝수 번째 차례를 진행한다. 게임 시작 시 0 부터 n − 1 까지 고유한 www.acmic..

[백준 4195] 친구 네트워크 [Java]

풀이 입력받은 이름에 대해 공통 부모를 갱신하며, 집합의 크기를 출력해야 되는 문제다. 공통 부모와, 집합의 크기를 저장할 parents, count 배열을 선언해주자. 문제에서 입력받은 친구 관계 F에 대해 입력받은 이름의 수는 최대 2F가 될 것이다. 때문에 위에서 선언한 배열의 크기 또한 2F로 할당받아야 한다. 모든 집합은 자기 자신에 대해 크기가 1이기에 count 배열은 1로 초기화 해주면 된다. 알다시피 parents 배열은 int형을 저장하는 배열이다. 때문에 입력받은 String형에 대해서는 Disjoint Set 구현이 불가능하다. 또한, parents 배열의 초깃값 설정을 할 때 자기 자신의 번호로 초기화를 해야하므로 String형 parent로 선언한다 하더라도 입력을 모두 받은 후..

[백준 1976] 여행 가자 [Java]

풀이 이전에 풀었던 문제의 확장판이다. [백준 17352] 여러분의 다리가 되어 드리겠습니다! [Java] 풀이 N + 1개의 집합 1 ~ N에 대해 공통 부모가 다른 경우를 찾아 연결해주면 되는 문제다. 우선, 입력으로 두 집합을 입력받아 union해주자. 모든 입력을 받았다면, parents에 자신의 부모 집합의 번호 kyr-db.tistory.com 입력에 따라 union을 해주고, 최대 1000개 까지 주어지는 최대 200이하의 도시에 대해 여행계획이 가능한지, 즉 공통 부모가 다르지 않은지 확인하는 문제다. 입력받은 i번째 줄의 j번이 1이라면 i 에서 j는 연결된 도시이다. 마지막에 입력되는 여행 계획은 결국 도시들이 하나로 연결이 되어있는지 여부에 따라 여행 가능 여부가 결정된다. 즉, 공통..

[백준 17352] 여러분의 다리가 되어 드리겠습니다! [Java]

풀이 N + 1개의 집합 1 ~ N에 대해 공통 부모가 다른 경우를 찾아 연결해주면 되는 문제다. 우선, 입력으로 두 집합을 입력받아 union해주자. 모든 입력을 받았다면, parents에 자신의 부모 집합의 번호가 적혀있을 것이다. 반복문을 돌며, 부모 집합의 번호가 다르다면 두 집합은 연결되어 있지 않으므로 두 집합을 연결할 수 있도록 번호를 출력해주면 되는 문제다. 소스코드 소스코드 보기 출처

[백준 28270] Marked-Numbered [Python]

풀이 트리로 주어지는 목차의 정보를 글머리 번호 형태로 바꾸면 되는 문제다. 아래 조건에 따라 변환할 수 있다. i 번째 수가 i - 1번째 수보다 작다면, 상위 글머리 번호부터 변환해주어야 한다. i 번째 수가 i - 1번째 수보다 크다면, 글머리 번호 형태에 따라 1로 변해야 한다. i 번째 수가 i - 1번째 수와 동일하다면, 이미 존재하는 목차이므로 i - 1번째 수의 글머리 번호 형태 + 1로 변해야 한다. 먼저 i번째 수가 i - 1번째 수보다 작은 경우다. 상위 글머리 번호부터 변환해주어야 하기에 이전에 기록된 하위 글머리 번호에 대해 누적된 수들을 0으로 초기화 하는 과정이 시간초과의 원인이 되었다. 이번 기회에 알게 된 사실인데, 문제를 틀렸거나 부분점수를 얻은 경우 '내 제출' 란에서 ..