From e683da26f836435adb024f0154696581045fb0c4 Mon Sep 17 00:00:00 2001 From: m4ushold Date: Tue, 12 Nov 2024 21:08:20 +0900 Subject: [PATCH] add: 2024-autumn-exercise/dp.md --- slides/2024-autumn-exercise/dp.md | 278 ++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 slides/2024-autumn-exercise/dp.md diff --git a/slides/2024-autumn-exercise/dp.md b/slides/2024-autumn-exercise/dp.md new file mode 100644 index 0000000..cb89dc0 --- /dev/null +++ b/slides/2024-autumn-exercise/dp.md @@ -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 \ No newline at end of file