Skip to content

Commit

Permalink
2024 Round 1 문제 및 풀이
Browse files Browse the repository at this point in the history
  • Loading branch information
myungwoo committed Aug 12, 2024
1 parent b4a48c2 commit d79fcea
Show file tree
Hide file tree
Showing 22 changed files with 1,454 additions and 12 deletions.
25 changes: 13 additions & 12 deletions pages/2024/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ const year = 2024;


const problems = {
round1: [ /*
["round1_p1", "[연습문제] 인류의 적 모기 퇴치"],
["round1_p2", "[연습문제] 카트라이더 보드게임"],
["round1_1", "메이플스토리 새로운 직업 고르기"],
["round1_2", "게임 안에서 책을 읽을 수 있다구요?"],
["round1_3", "더하기와 곱하기"],
["round1_4", "언제까지 기다려야"],
["round1_5", "짠돌이 구단주"],
["round1_6", "몬스터 격퇴 원정단"],
["round1_7", "욕심 많은 신년 운세"],
["round1_8", "별자리 그리기"],
*/ ],
round1: [
["round1_p1", "[연습문제] 메이플스토리 새로운 직업 고르기"],
["round1_p2", "[연습문제] 별자리 그리기"],
["round1_1", "초밥"],
["round1_2", "무한 길이 물풍선"],
["round1_3", "커닝시티 헤어샵"],
["round1_4", "오르락 내리락"],
["round1_5", "게임"],
["round1_6", "어디로 피해야하지?"],
["round1_7", "골드리치의 비밀 금고"],
["round1_8", "브레이크가 고장난 카트"],
["round1_9", "1-2-3 퍼즐"],
],
round2a: [ /*
["round2a_1", "오솔길"],
["round2a_2", "주사위 대체"],
Expand Down
107 changes: 107 additions & 0 deletions pages/2024/round1_1.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import {
Examples,
Input,
Output,
Figure,
PostLayout,
Simulators,
Solution,
Subtask,
} from "components";

export const meta = {
title: "초밥",
year: 2024,
stage: "Round 1",
};

export default ({ children }) => (
<PostLayout meta={meta}>{children}</PostLayout>
);

<div style={{ display: "flex" }}>
<Figure
src="/2024/1-1.9c7b433c967133f1.png"
width={800}
/>
</div>

반쵸는 유명 초밥집의 주인이다.
반쵸는 오늘 바다에서 채집한 재료로 "복어 특초밥" $A$ 개와
"바다포도 특초밥" $B$ 개를 만들었다.

반쵸는 이 초밥들을 모두 배달하기 위해 포장해야 한다.
하나의 상자에는 최대 $4$ 개의 초밥을 담을 수 있다. 단, 각 상자에는
최소 "복어 특초밥" $1$ 개와 "바다포도 특초밥" $1$ 개가 담겨야 한다.

반쵸가 모든 초밥을 포장할 수 있는 상자의 최소 개수를 구하는 프로그램을 작성하라.

## 입력 형식

첫 줄에 테스트 케이스의 수를 나타내는 정수 $T$가 주어진다. ($1 \le T \le 1\,000$)

이어지는 $T$ 개의 줄에는 차례로 각 테스트 케이스가 주어진다.
각 줄은 복어 특초밥의 개수를 나타내는 정수 $A$와
바다포도 특초밥의 개수를 나타내는 정수 $B$가
공백으로 구분되어 주어진다.
($1 \le A, B \le 500\,000\,000$)

## 출력 형식

$T$ 개의 줄에 걸쳐 답을 출력한다.
$i$ 번째 줄에는 $i$ 번째 테스트 케이스에 대한 답을 출력한다.
만약, 문제의 조건을 만족하면서 모든 초밥을 포장하는 것이 불가능한 경우 $-1$을 출력한다.

## 예제

<Examples>
{/* prettier-ignore */}
<Input>
3
2 2
5 2
5 1
</Input>
{/* prettier-ignore */}
<Output>
1
2
-1
</Output>
</Examples>

## 예제 설명

첫 번째 테스트 케이스에서 하나의 상자에 $4$ 개의 초밥을 모두 담을 수 있다.

두 번째 테스트 케이스에서는 한 상자에 복어 특초밥 $3$ 개와 바다포도 특초밥 $1$ 개,
다른 상자에 복어 특초밥 $2$ 개와 바다포도 특초밥 $1$ 개를 담을 수 있다.

세 번째 테스트 케이스에서는 바다포도 특초밥이 $1$ 개밖에 없어서
문제의 조건을 만족하면서 상자에 담는 것이 불가능하다.

## 채점 방식

입력 케이스들은 다음과 같은 종류로 구별되며, 한 종류의 케이스를 다 맞혀야 그 종류에 배정된 점수를 받을 수 있다.

<Subtask index={1} score={31}>
$A, B \le 4$
</Subtask>
<Subtask index={2} score={17}>
불가능한 경우는 주어지지 않음.
</Subtask>
<Subtask index={3} score={52}>
추가적인 제한 조건이 없음.
</Subtask>

## 해설

<Solution>
일반성을 잃지 않고 $A \le B$라고 하자.
$A > B$이면 $A$와 $B$를 교환해서 생각할 수 있다.

만약 $3A < B$라면 초밥을 어떻게 옮기더라도 모두 옮길 수 없다.
그렇지 않은 경우, 매번 $\min(A+B, 4)$ 개의 초밥을 옮기면서
여전히 $3\min(A,B) \ge \max(A,B)$가 성립하도록 만들 수 있다.
따라서 $\lceil \frac{A+B}{4} \rceil$ 번 만에 모든 초밥을 옮길 수 있다.
</Solution>
109 changes: 109 additions & 0 deletions pages/2024/round1_2.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
Examples,
Input,
Output,
Figure,
PostLayout,
Simulators,
Solution,
Subtask,
} from "components";

export const meta = {
title: "무한 길이 물풍선",
year: 2024,
stage: "Round 1",
};

export default ({ children }) => (
<PostLayout meta={meta}>{children}</PostLayout>
);

<div style={{ display: "flex" }}>
<Figure
src="/2024/2-1.f5057fdd9cbed9f9.png"
width={300}
/>
</div>

배찌는 무한한 길이의 폭발 범위를 가지는 물풍선 스킬을 터득하였다. 이 스킬을
사용하기 위해 배찌는 우선 2차원 평면의 $N$ 개의 좌표에 물풍선을 놓는다.

스킬을 사용하면 동일한 $x$ 좌표를 가진 두 점에 물풍선이 있는 경우 해당 $x$ 좌표의 모든
점이 물풍선의 폭발 범위에 들어간다. 즉, 수직인 직선 전부가 물풍선의 폭발 범위가 된다.

또, 동일한 $y$ 좌표를 가진 두 점에 물풍선이 있는 경우 해당 $y$ 좌표의 모든
점이 물풍선의 폭발 범위에 들어간다. 즉, 수평인 직선 전부가 물풍선의 폭발 범위가 된다.

배찌가 물풍선을 놓은 좌표들을 입력으로 받아 물풍선의 폭발 범위가 되는 수직, 수평
직선의 개수를 계산하는 프로그램을 작성하라. 서로 다른 두 개 이상의 물풍선 쌍이 만드는
폭발 범위가 완전히 일치하는 경우, 즉 동일한 직선이 되는 경우는 하나로 세어야 한다.

## 입력 형식

첫 줄에 점의 개수를 나타내는 정수 $N$이 주어진다. ($1 \le N \le 100\,000$)

이어지는 $N$ 개의 줄의 $i$ 번째 줄에는
$i$ 번째 물풍선이 놓인 좌표를 나타내는 두 정수 $x_i$와 $y_i$가
공백으로 구분되어 주어진다.
($1 \le x_i, y_i \le 1\,000\,000\,000$)

주어지는 물풍선의 좌표는 서로 다르다.

## 출력 형식

첫 줄에 물풍선의 폭발 범위가 되는 수직, 수평 직선의 개수를 출력한다.

## 예제

<Examples>
{/* prettier-ignore */}
<Input>
4
1 1
2 2
3 1
2 1
</Input>
{/* prettier-ignore */}
<Output>
2
</Output>
</Examples>

## 예제 설명

물풍선이 놓인 점 $(2, 2)$와 $(2, 1)$을 보면 $x$ 좌표가 같으므로 수직인 직선
하나가 폭발 범위가 된다.\
점 $(1, 1)$과 $(2, 1)$을 보면 $y$ 좌표가 같으므로 수평인 직선 하나가 폭발 범위가 된다.\
점 $(2, 1)$과 $(3, 1)$을 보면 $y$ 좌표가 같으므로 수평인 직선 하나가 폭발 범위가 된다.\
점 $(1, 1)$과 $(3, 1)$을 보면 $y$ 좌표가 같으므로 수평인 직선 하나가 폭발 범위가 된다.\
그런데, 수평인 직선 $3$ 개는 모두 완전히 일치하므로 $1$ 개로 세어야 한다.

따라서 이 경우의 답은 $2$가 된다.

## 채점 방식

입력 케이스들은 다음과 같은 종류로 구별되며, 한 종류의 케이스를 다 맞혀야 그 종류에 배정된 점수를 받을 수 있다.

<Subtask index={1} score={13}>
$N \le 20;$ $x_i, y_i \le 20$
</Subtask>
<Subtask index={2} score={16}>
$N \le 1\,000$; $x_i, y_i \le 100$
</Subtask>
<Subtask index={3} score={14}>
$N \le 1\,000$
</Subtask>
<Subtask index={4} score={57}>
추가적인 제한 조건이 없음.
</Subtask>

## 해설

<Solution>
어떤 $x$ 좌표에 대해 그 $x$ 좌표를 가지는 물풍선이 두 개 이상 있으면 수직으로 폭발이 일어난다.
마찬가지로, 어떤 $y$ 좌표에 대해 그 $y$ 좌표를 가지는 물풍선이 두 개 이상 있으면 수평으로 폭발이 일어난다.
이러한 점을 이용하여, 정렬 혹은 map 등의 자료구조를 이용하여
문제를 $\mathcal{O}\left( N \lg N \right)$ 시간복잡도에 해결할 수 있다.
</Solution>
123 changes: 123 additions & 0 deletions pages/2024/round1_3.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import {
Examples,
Input,
Output,
Figure,
PostLayout,
Simulators,
Solution,
Subtask,
} from "components";

export const meta = {
title: "커닝시티 헤어샵",
year: 2024,
stage: "Round 1",
};

export default ({ children }) => (
<PostLayout meta={meta}>{children}</PostLayout>
);

<div style={{ display: "flex" }}>
<Figure
src="/2024/3-1.e20a4c08444ac688.png"
width={600}
/>
</div>

‘커닝시티 헤어샵’에는 원장 돈 지오바네와 보조 안드레아가 일하고 있다.
어느 날, 이 둘에게 헤어 스타일링을 받으려는 고객 $N$ 명이 한 줄로 기다리고 있다.

돈 지오바네와 안드레아는 각 고객이 서비스받는 시간을 알고 있다.
고객들은 줄을 선 순서대로 서비스를 받아야 한다.
돈 지오바네와 안드레아는 협력해서 일하여
최대 $2$ 명의 고객을 동시에 서비스할 수 있다.
만약 두 사람이 동시에 $2$ 명의 고객을 서비스하는 경우,
두 고객 중 서비스받는 시간이 오래 걸리는 쪽의 시간이 걸린다.

돈 지오바네와 안드레아가 모든 고객을 서비스하는 데 걸리는 최소 시간을 계산하는 프로그램을 작성하라.

## 입력 형식

첫 줄에 고객의 수를 나타내는 정수 $N$이 주어진다. ($1 \le N \le 500\,000$)

그다음 줄에 $N$ 명의 고객이 서비스받는 시간을 나타내는 정수 $N$ 개가
줄을 선 순서대로 공백으로 구분되어 주어진다.

각 고객이 서비스받는 시간은 $1$ 이상 $1\,000\,000\,000$ 이하다.

## 출력 형식

첫 줄에 모든 고객을 서비스하기 위해 필요한 최소 시간을 출력한다.

## 예제 1

<Examples>
{/* prettier-ignore */}
<Input>
4
2 3 4 3
</Input>
{/* prettier-ignore */}
<Output>
7
</Output>
</Examples>

## 예제 2

<Examples>
{/* prettier-ignore */}
<Input>
4
1 3 3 1
</Input>
{/* prettier-ignore */}
<Output>
5
</Output>
</Examples>

## 예제 설명

입력 예제 1에서 첫 번째와 두 번째 고객을 동시에 서비스해서 시간 $3$이 걸리고,
세 번째와 네 번째 고객을 동시에 서비스해서 시간 $4$가 걸린다. 따라서, 전체 시간은 $7$이며
이 방법이 최선이다.

입력 예제 2에서 첫 번째 고객을 서비스하여 시간 $1$이 걸리고, 두 번째와 세 번째
고객을 동시에 서비스하여 시간 $3$이, 네 번째 고객을 서비스하여 시간 $1$이 걸린다.
따라서, 전체 시간은 $5$이며 이 방법이 최선이다.

## 채점 방식

입력 케이스들은 다음과 같은 종류로 구별되며, 한 종류의 케이스를 다 맞혀야 그 종류에 배정된 점수를 받을 수 있다.

<Subtask index={1} score={19}>
$N \le 4$
</Subtask>
<Subtask index={2} score={14}>
고객이 서비스받는 시간은 모두 동일함.
</Subtask>
<Subtask index={3} score={67}>
추가적인 제한 조건이 없음.
</Subtask>

## 해설

<Solution>
DP를 사용해서 문제를 풀 수 있다.
$D_i$를 $i$ 번째 고객부터 서비스할 때 걸리는 최소 시간이라고 하자.
총 $N$ 명의 고객이 있고, 각 고객이 서비스받는 데 걸리는 시간을 $A_1, A_2, \dots, A_N$이라고 하자.

그러면 $D$ 배열의 값은 다음과 같다:
$$
\begin{align*}
D_N & = A_N, \\
D_{N-1} & = \max(A_{N-1}, A_N), \\
D_i & = \min(A_i + D_{i+1}, \max(A_i, A_{i+1}) + D_{i+2}) \quad \forall i \leq N - 2.
\end{align*}
$$

최종적으로 $D_1$의 값이 정답이 된다.
</Solution>
Loading

0 comments on commit d79fcea

Please sign in to comment.