Teknik Divide and Conquer dalam Dynamic Programming
(Post in Indonesian) Trik khusus dalam Dynamic Programming.
Teknik Divide and Conquer dalam Dynamic Programming
DISCLAIMER: Post ini memuat slide saja. Slide ini dibuat waktu saya diminta bantuan oleh Pak Denny untuk mengisi kelas Competitive Programming waktu saya masih kuliah. Sekarang, saya sudah tidak lagi aktif dalam dunia competitive programming. Mohon maaf apabila ada kesalahan 🙏🙏🙏, source code untuk latexnya pun sudah hilang.
Materi
Slide bisa diunduh disini.
Contoh soal
SPOJ LARMY
Untuk soal, klik disini
Solusinya (dalam C++) bisa dilihat di bawah:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <bits/stdc++.h>
#define INF 1e9
using namespace std;
int N, K, H[5005];
int C[5005][5005];
int greater_heights[5005];
int dp[5005][5005];
void precompute_C() {
// Hitung banyaknya tentara yang lebih tinggi di sebelah kiri
// Ini awalnya akan menjadi nilai dari C[1][i]
for (int i = 1; i <= N; ++i) {
for (int j = 1; j < i; ++j) {
if (H[j] > H[i])
++greater_heights[i];
}
}
// Precompute C[i][j]
for (int i = 1; i <= N; ++i) {
for (int j = i; j <= N; ++j) {
C[i][j] = greater_heights[j] + C[i][j-1];
}
// Untuk membuang orang ke-i untuk menghitung C[i+1][j]
// menggunakan array greater_heights[]
for (int j = i+1; j<= N; ++j) {
if (H[j] < H[i]) {
--greater_heights[j];
}
}
}
}
// Basecase DP
void fill_basecase() {
for (int i = 1; i <= N; ++i)
dp[0][i] = INF;
for (int i = 1; i <= K; ++i)
dp[i][0] = INF;
}
void fill_table_row(int i, int l, int r, int opt_l, int opt_r) {
if (l > r)
return;
int mid = (l+r)>>1;
// mendapatkan opt_mid sambil mengisi nilai dp
int opt_mid = -1;
for (int k = opt_l; k <= opt_r; ++k) {
// apabila k >= mid, sudah tidak termasuk batasan rekurens
if (k >= mid)
break;
int val = dp[i-1][k] + C[k+1][mid];
if ((opt_mid == -1) || (dp[i][mid] > val)) {
opt_mid = k;
dp[i][mid] = val;
}
}
fill_table_row(i, l, mid-1, opt_l, opt_mid);
fill_table_row(i, mid+1, r, opt_mid, opt_r);
}
int main() {
cin.sync_with_stdio(0);
cin.tie(0);
cin >> N >> K;
for(int i=1;i<=N;++i) {
cin >> H[i];
}
precompute_C();
fill_basecase();
// Isi tabel DP
for (int i=1;i<=K;++i) {
fill_table_row(i, 1, N, 0, N-1);
}
cout << dp[K][N] << '\n';
return 0;
}
Kattis famouspagoda
Untuk soal, klik disini
This post is licensed under CC BY 4.0 by the author.