-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
278 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
--- | ||
marp: true | ||
--- | ||
|
||
# Dynamic Programming | ||
소프트웨어학부 진민성 | ||
|
||
--- | ||
|
||
# 쉬운 계단 수 | ||
|
||
## 요약 | ||
이 수는 인접한 모든 자리의 차이가 1이다. 이런 수를 계단 수라고 한다. | ||
N이 주어질 때, 길이가 N인 계단 수가 총 몇 개 있는지 구해보자 | ||
|
||
## 제한 | ||
$1\leq N \leq 100, N \in \mathbb{N}$ | ||
|
||
--- | ||
|
||
## 풀이 | ||
DP[i][j]를 i로 끝나는 j자리 계단수의 개수라고 하자. | ||
- $1 \leq i \leq 8$ | ||
$DP[i][j] = \sum DP[i-1][j-1] + DP[i+1][j-1]$ | ||
- $i==0$ | ||
$DP[i][j] = DP[i+1][j-1]$ | ||
- $i==9$ | ||
$DP[i][j] = DP[i-1][j-1]$ | ||
|
||
--- | ||
|
||
# 가장 긴 증가하는 부분 수열 4 | ||
|
||
## 요약 | ||
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구해라 | ||
|
||
## 제한 | ||
수열 $A$의 크기 $N (1 ≤ N ≤ 1,000)$ | ||
$(1 ≤ Ai ≤ 1,000)$ | ||
|
||
--- | ||
|
||
## 풀이 | ||
N제한이 1000이므로 N^2풀이가 가능하다. | ||
$DP[i]$를 $i$번째 까지의 가장 긴 증가하는 부분수열의 길이라고하자. | ||
이전 배열을 보면서 A[i]보다 작은 수 중에 가장 큰 증가하는 부분수열의 길이+1을 DP[i]로 계산해주면 된다. | ||
$DP[i] = (\max _{j=1}^{i-1}{DP[j]}) +1, where A[j] < A[i]$ | ||
|
||
|
||
binary search 혹은 segment tree를 이용하여 O(NlogN)에 푸는 방법또한 존재한다. | ||
https://www.acmicpc.net/problem/14003 | ||
|
||
--- | ||
|
||
# LCS 2 | ||
|
||
## 요약 | ||
두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제 | ||
|
||
## 제한 | ||
문자열은 알파벳 대문자로만 이루어져 있으며, 최대 1000글자로 이루어져 있다. | ||
|
||
--- | ||
|
||
## 풀이 | ||
단순하게 LCS를 구해주면 되는 문제 | ||
http://boj.kr/bd070e3638e640be9025c79ce86c9e8d | ||
|
||
--- | ||
|
||
# 1학년 | ||
|
||
## 요약 | ||
숫자가 주어졌을 때, 상근이가 만들 수 있는 올바른 등식의 수를 구하는 프로그램을 작성하시오. | ||
|
||
## 제한 | ||
첫째 줄에 숫자의 개수 N이 주어진다. | ||
(3 ≤ N ≤ 100) 둘째 줄에는 0 이상 9 이하의 정수 N개가 공백으로 구분해 주어진다. | ||
상근이는 아직 학교에서 음수를 배우지 않았고, 20을 넘는 수는 모른다. | ||
답은 $2^{63}-1$이하임이 보장된다. | ||
|
||
--- | ||
|
||
## 풀이 | ||
|
||
상근이는 20이상의 수를 모른다는 조건이 있으므로 1~20사이의 수의 개수만을 확인하면 된다. | ||
$DP[i][j]$를 i개의 수를 사용하여 j를 만드는 경우의 수라고 가정해자. | ||
|
||
$DP[i][j] = DP[i-1][j-A[i]] + DP[i-1][j+A[i]], where 1 \leq j \leq 20$ | ||
|
||
|
||
--- | ||
|
||
# 배수 찾기 | ||
|
||
## 요약 | ||
양의 정수 n이 주어졌을 때, n의 배수 중에서 0과 1로만 이루어진 m을 찾는 프로그램을 작성하시오. n은 200을 넘지 않고, m은 0보다 큰 양의 정수이며, 100자리를 넘지 않아야 한다. | ||
|
||
## 제한 | ||
$N \leq 200$ | ||
$M \gt 0$ | ||
M은 100자리를 넘지 않아야 한다. | ||
|
||
--- | ||
|
||
## 풀이 | ||
DP[M][mod][use]를 M자리수 일때 N으로 나눈 나머지가 mod이고 1의 사용 여부를 use라고 하자. | ||
그렇게 하면 DP를 돌리고 역추적하여 M자리 자연수를 구할 수 있다. | ||
|
||
혹은 bfs를 알고 있다면 bfs로 풀 수 있다. | ||
$(a+b+c) \equiv (a+b)+c \mod{n}$를 이용하여 a%n을 저장해주면서 $a*10, a*10+1$로 bfs를 돌리다가 a가 0이 되면 문자열을 출력하고 종료하면 된다. | ||
|
||
--- | ||
|
||
# 축구 | ||
## 요약 | ||
90분동안 5분으로 나누어진 경기를 분석하여 a팀이 득점할 확률과 b팀이 득점할 확률 퍼센트 단위로 주어진다. | ||
경기가 끝난 후 적어도 한 팀이 골을 소수로 득점할 확률을 구하는 문제 | ||
|
||
## 제한 | ||
주어지는 확률은 모두 0보다 크거나 같고 100보다 작거나 같은 정수 | ||
정답과의 절대/상대 오차가 10-6이내 | ||
|
||
--- | ||
|
||
## 풀이 | ||
|
||
최대 $18$골을 넣을 수 있다. | ||
따라서 넣을 수 있는 소수개수의 골은 $2,3,5,7,11,13,17$이다. | ||
|
||
우선 $A$팀이 득점할 확률을 $P_{A}$, $B$팀이 득점할 확률을 $P_{B}$라고 하자 | ||
|
||
A팀이 소수점수를 득점할 확률은 다음과 같이 구해줄 수 있다. | ||
$\sum_{i} {18 \choose i} * {P_{A}}^{i} * {(1-P_{A})}^{18-i}, \in \set{2,3,5,7,11,13,17}$ | ||
|
||
여기에서 이항계수 ${n \choose r}$은 DP[n][r] = DP[n-1][r-1] + DP[n-1][r]로 구해줄 수 있다. | ||
|
||
--- | ||
|
||
# 행렬 곱셈 순서 | ||
|
||
## 요약 | ||
행렬 N개의 크기가 주어졌을 때, 모든 행렬을 곱하는데 필요한 곱셈 연산 횟수의 최솟값을 구하는 문제 | ||
|
||
## 제한 | ||
행렬의 개수 N(1 ≤ N ≤ 500) | ||
행렬의 크기 r과 c(1 ≤ r, c ≤ 500) | ||
|
||
--- | ||
|
||
## 풀이 | ||
$DP[i][j]$를 $i$번째 행렬 부터 $j$번째 행렬까지의 최소 곱셈 횟수라고 하자 | ||
$DP[i][j]=\min(DP[i][k]+DP[k+1][j]+R[i]*C[k]*C[j]), (i\leq k \lt j)$ | ||
그러면 i+j=d라고 할때 d=2부터 n까지 돌면서, 즉 대각선 순서대로 보면서 구간을 DP해줄 수 있다. | ||
|
||
--- | ||
|
||
# 헌책방 | ||
|
||
## 요약 | ||
헌책방은 책을 소설, 만화, 잡지등 10개의 장르로 분류한다. | ||
같은 장르의 책을 T권 매입할 때, 책 한 권 당 매입 가격이 기준 가격보다 T-1원 높아진다 | ||
책 N권 중 K권을 팔려고 한다. | ||
총 매입 가격의 최댓값을 구하는 문제 | ||
|
||
# 제한 | ||
$2 ≤ N ≤ 2000, 1 ≤ K < N$ | ||
가격 $C_i$, 장르 $G_i$ $(1 ≤ Ci ≤ 105, 1 ≤ Gi ≤ 10)$ | ||
|
||
--- | ||
|
||
## 풀이 | ||
우선 같은 장르의 책을 판매하는 경우 가격이 큰 순서대로 판매하는 것이 이득이므로 가격 내림차순으로 정렬한다. | ||
$PRICE[i][j]$를 장르 i를 j개 팔았을때 얻을수 있는 최대 금액이라고 하고 미리 전처리하자. | ||
|
||
$DP[i][j]$를 $1~i$번째 장르에서 j개를 판매 했을때 가격이라고 정의하자. | ||
그러면 아래와 같이 전이할 수 있다. | ||
$DP[i][j] = \max(DP[i-1][j-l] + PRICE[i][l]), 1\leq l\leq $ | ||
|
||
--- | ||
|
||
# 248 게임 | ||
|
||
## 요약 | ||
이 게임은 N개의 양수로 시작하여, 인접한 두 개의 같은 수를 1 큰 수로 바꿀 수 있다. | ||
목표는 가능한 모든 합병이 끝났을 때 수열에서 가장 큰 수를 최대화하는 문제 | ||
|
||
## 제한 | ||
$(2 ≤ N ≤ 248)$ | ||
$1\leq A_i \leq 40$ | ||
|
||
--- | ||
|
||
## 풀이 | ||
dp[i][j] = [i, j]구간에서 만들 수 있는 유일한 정수 중 최댓값이라고 하자. | ||
|
||
유일한 정수라는 것은 숫자들을 합쳐서 남는 단 한 개의 정수를 의미한다. | ||
만약 한 개의 정수를 남기지 못한다면 0으로 정의한다. | ||
|
||
dp[i][k]와 dp[k+1][j]가 같은 경우 dp[i][j] = dp[i][k] + 1이 된다. | ||
|
||
--- | ||
|
||
# NP-hard | ||
|
||
## 요약 | ||
변형된 외판원 문제(TSP)로, N개의 도시를 한 번씩 방문하며 소요 시간을 최소화 | ||
각 도시 간의 거리가 주어지고, K번 도시를 방문할 때는 K보다 작은 도시들을 순서대로 모두 방문해야 한다. | ||
첫 도시와 마지막 도시는 동일할 필요가 없으며, 최종 목표는 최소 소요 시간을 찾는 문제 | ||
|
||
## 풀이 | ||
최적해는 감소하다가 1을 찍고 증가하는 형태 | ||
1부터 시작해서 정점을 양끝에 추가하는 형태의 DP를 해주면 된다. | ||
$D[s][e] = min(f(nxt,e)+G[nxt][s], f(s,nxt)+G[e][nxt])$ | ||
|
||
--- | ||
|
||
# 산책 | ||
|
||
## 요약 | ||
상근이는 (1,1)에서 (H,W)까지 산책하며 각 교차로에 적힌 '오'(오른쪽)와 '아'(아래)라는 문자에 따라 이동 | ||
'오'일 경우 '아'로 바꾸고 오른쪽으로, '아'일 경우 '오'로 바꾸고 아래로 진행 | ||
도로의 끝에 도달하면 산책을 종료하며, N번째 산책 경로를 구하는 문제 | ||
|
||
## 제한 | ||
$1 ≤ H,W ≤ 1000, 1 ≤ N ≤ 107$ | ||
|
||
--- | ||
|
||
## 풀이 | ||
각 교차로에 홀수번 방문하면 적힌대로 짝수번 방문하게 되면 적혀있는것과 반대방향으로 이동하면 된다. | ||
각 교차로에 방문하는 횟수는 DP를 이용하여 구해줄 수 있다. | ||
아래와 비슷하게 현재 DP[i][j]에서 아래와 위로 방문횟수를 전이해주면 된다. | ||
$DP[i+1][j] += DP[i][j]+!A[i][j]>>1$ | ||
$DP[i][j+1] += DP[i][j]+A[i][j]>>1$ | ||
|
||
--- | ||
|
||
# 가로등 끄기 | ||
|
||
## 요약 | ||
마징가는 가로등을 끄기 위해 5시 정각에 한 가로등 아래에서 출발 | ||
가로등의 위치와 소비 전력이 주어질 때, 마징가는 1m/sec의 속도로 이동하며 가로등을 끄는 순서를 정해 전력 낭비를 최소화하여 전력의 최솟값을 구하는 문제 | ||
|
||
## 제한 | ||
가로등의 개수를 나타내는 정수 $N(1 ≤ N ≤ 1,000)$ | ||
마징가 처음에 위치하는 가로등 번호 $M \leq N$ | ||
가로등의 위치 $D(0 ≤ D ≤ 1,000)$ | ||
가로등의 전력소비량 $W(1 ≤ W ≤ 100,000,000)$ | ||
|
||
낭비되는 전력의 최솟값은 $1,000,000,000$ 보다는 항상 작음이 보장됨 | ||
|
||
--- | ||
|
||
## 풀이 | ||
http://boj.kr/a877b0eebe9b40fd812101d3002c51f9 | ||
|
||
|
||
--- | ||
|
||
# 다각형의 분할 | ||
## 요약 | ||
N각형이 주어졌을 때, 가능한 삼각분할의 경우의 수와 사각분할의 경우의 수를 구하는 문제 | ||
회전, 또는 대칭을 이용한 경우에는 같은 것으로 세지 않고 다른 것으로 센다. | ||
1e9으로 나눈 나머지 출력 | ||
|
||
## 제한 | ||
$N(3 ≤ N ≤ 1,000)$ | ||
|
||
--- | ||
|
||
## 풀이 | ||
|
||
단순한 N각형의 삼각분할은 카탈란 수임이 잘 알려져 있다. | ||
하지만 사각분할은 귀찮고 N제한이 1000밖에 안되니 DP로 구해주자. | ||
$dpt[i] += (dpt[j]*dpt[i-j+1]) \mod {1,000,000,000}$ | ||
$dps[i] += (dps[j]*dps[k]*dps[i-j-k+2]) \mod {1,000,000,000}$ | ||
http://boj.kr/e0a2398c686e4583b344b15f9a93b8e0 |