forked from cp-algorithms/cp-algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_divide_and_conquer_dp.cpp
78 lines (61 loc) · 1.71 KB
/
test_divide_and_conquer_dp.cpp
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
// https://codeforces.com/contest/1527/problem/E
#include <bits/stdc++.h>
using namespace std;
#include "divide_and_conquer_dp.h"
vector<int> ar;
/// O(m * n^2) DP, ignoring complexity of C(i, j)
int brute_force() {
for (int j = 0; j < n; j++)
dp_before[j] = C(0, j);
for (int i = 1; i < m; i++) {
for (int j = 0; j < n; j++) {
dp_cur[j] = INT_MAX;
for (int k = 0; k <= j; k++) {
dp_cur[j] = min(dp_cur[j], (k ? dp_before[k - 1] : 0) + C(k, j));
}
}
dp_before = dp_cur;
}
return dp_before[n - 1];
}
// sum of last occurrence of x - first occurrence of x for all unique x in the range
long long C(int i, int j) {
map<int, int> last;
int cost = 0;
for (int l = i; l <= j; l++) {
int x = ar[l];
if (last.count(x))
cost += (l - last[x]);
last[x] = l;
}
return cost;
}
void test_handcrafted_case() {
ar = vector<int>({
32, 8, 32, 32, 32, 34, 38, 38, 39, 32, 22, 29, 39,
5, 5, 32, 5, 32, 32, 22, 10, 22, 8, 35, 38, 23, 29,
9, 8, 29, 34, 32, 11, 29, 22, 32, 38, 38, 32,
});
m = 3;
n = ar.size();
dp_before.resize(n, 0), dp_cur.resize(n, 0);
assert(solve() == 30);
}
void test_random_cases(int t, int maxn, int maxv) {
mt19937 rng(0);
for (int i = 0; i < t; i++) {
n = rng() % maxn + 1;
dp_before.resize(n, 0), dp_cur.resize(n, 0);
ar.clear();
for (int i = 0; i < n; i++)
ar.push_back(rng() % maxv + 1);
for (m = 1; m <= n; m++) {
assert(solve() == brute_force());
}
}
}
int main() {
test_handcrafted_case();
test_random_cases(100, 10, 5);
return 0;
}