본문 바로가기

백준/DP

(67)
백준 2092 - 집합의 개수 icpc.me/2092 1 이상 T 이하의 값을 가진 수 A개가 주어지면 개중에 K개 뽑아서 집합을 만들 때 각 집합의 원소 개수가 S 이상 B 이하인 집합의 개수를 구하는 문제이다. (순서가 다른 것은 같은 것으로 친다.) 이 문제는 푼 사람이 얼마 안되지만 부분집합 개수와 관련된 연산을 하는 문제는 dp의 주요 유형중 하나이다. Solution 일단 A개의 원소들을 각 수가 몇 개 존재하는지 기록하자. 구현에서는 배열을 사용하였다. dp 테이블은 이차원으로 설계한다. dp[n][k] -> n 이하의 값을 가진 수 중에서 k개를 선택해 집합을 생성하는 경우의 수 이때 공집합을 인정하여 dp[0][0] = 1이다. 1부터 T까지 반복문을 돌면서 단일 숫자로 집합을 생성하는 경우(ex {5}, {5, 5}..
백준 16456 - 하와와 대학생쨩 하와이로 가는 거시와요~ icpc.me/16456 몇가지 항에 대해 직접 손으로 경우의 수를 찾아보면 $f(n) = f(n - 1) + f(n - 3)$ 형태의 점화식이 성립됨을 찾을 수 있다. DP를 통해 이 점화식을 풀자. 전체코드 더보기 #include #define mod 1000000009 using namespace std; using ll = long long; ll dp[50000]; int main() { int n; cin >> n; dp[0] = dp[1] = 1; dp[2] = 2; for (int i = 3; i < n; ++i) dp[i] = (dp[i - 1] + dp[i - 3]) % mod; cout
백준 15681 - 트리와 쿼리 주어진 입력으로 트리를 구성한다. 그리고 그래프 탐색을 통해 해당 노드의 깊이도 저장하도록 한다. 그 후 탑다운 DP를 통해 해당 노드가 가지는 자식의 갯수를 계산하여 출력하도록 하면 된다. 전체 코드 더보기 #include using namespace std; vector al[100001]; int depth[100001]; int dp[100001]; int build_tree(int v); int main() { memset(dp, -1, sizeof dp); ios::sync_with_stdio(false); cin.tie(0); int v, rt, qry; cin >> v >> rt >> qry; for (int i = 0; i > g..
백준 2056 - 작업 작업 간 선행관계가 제시되어 있으므로 작업들의 관계는 DAG가 되고 DP를 통해 각 작업을 끝내는데 필요한 최소시간을 찾아 더해주면 된다. 포레스트 형태에 대해 유의하여 구현한다. 전체 코드 더보기 #include using namespace std; using graph = vector; int finished[100001]; int fee[100001]; int memo[100001]; int dp(int node, graph &al); int main() { cin.tie(0); cout.tie(0); ios::sync_with_stdio(false); int n; cin >> n; memset(memo, -1, sizeof memo); graph task(n + 1); for (int i = 0;..
백준 1915 - 가장 큰 정사각형 www.acmicpc.net/problem/1915 2차원 배열에서 가장 큰 정사각형을 찾는 문제이다. 이 문제는 현재 위치에 정사각형이 존재할 경우(값이 1일 경우) 왼쪽, 위쪽, 왼쪽 위에 있는 원소의 최솟값을 더해 현재 인덱스까지의 가장 큰 정사각형의 길이를 저장할 수 있다. 예제를 통해 알아보자. 인덱스 (0, 0)처럼 왼쪽, 위쪽, 왼쪽 위의 원소를 볼 수 없거나 그 값이 0인 경우는 넘어간다. 인덱스 (1, 1)에서 왼쪽, 위쪽, 왼쪽 위를 살펴보면 위쪽의 값은 1이지만 그 외 값들은 전부 0이다. 세 원소의 최솟값이 0이므로 해당 인덱스까지 계산했을 때 정사각형의 최대 길이는 역시 1 + 0 = 1이다. 마찬가지로 인덱스 (1, 2), (1, 3), (2, 1)까지 계산했을 때 최대 정사각형..