-
Notifications
You must be signed in to change notification settings - Fork 9
/
asterix_the_gaul.cpp
148 lines (117 loc) · 3.22 KB
/
asterix_the_gaul.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
///4
#include <iostream>
#include <vector>
#include <map>
#include <tuple>
#include <cmath>
#include <limits>
#include <algorithm>
using namespace std;
struct DistanceTime {
long distance;
long time;
bool operator<(const DistanceTime& other) const {
return time < other.time;
}
};
int n; // number of moves
int m; // amount of magic potion
long D; // distance to panoramix
long T; // number of seconds it takes for the romans to reach the druid
vector<long> d; // traversed distance for each move
vector<long> t; // time required for each move
vector<long> s; // additional distance covered by every move after taking i gulps
void computeDistanceTimePairs(int i, int end, int gulps, long distance, long remainingTime, vector<DistanceTime> &distanceTime) {
if (remainingTime <= 0) {
return;
}
if (i == end) {
if (distance > 0) {
distanceTime.push_back({distance, T - remainingTime});
}
return;
}
// Use move
computeDistanceTimePairs(i + 1, end, gulps, distance + d[i] + s[gulps], remainingTime - t[i], distanceTime);
// Do not use move
computeDistanceTimePairs(i + 1, end, gulps, distance, remainingTime, distanceTime);
}
bool isFeasible(int gulps) {
// Split
vector<DistanceTime> distanceTime1;
vector<DistanceTime> distanceTime2;
computeDistanceTimePairs(0, n / 2, gulps, 0, T, distanceTime1);
computeDistanceTimePairs(n / 2, n, gulps, 0, T, distanceTime2);
// Sort by time
sort(distanceTime1.begin(), distanceTime1.end());
sort(distanceTime2.begin(), distanceTime2.end());
// Replace distance with max-distance for a given time
for (int i = 1; i < distanceTime1.size(); ++i) {
distanceTime1[i].distance = max(distanceTime1[i - 1].distance, distanceTime1[i].distance);
}
for (int i = 1; i < distanceTime2.size(); ++i) {
distanceTime2[i].distance = max(distanceTime2[i - 1].distance, distanceTime2[i].distance);
}
// The maximal element of a single list is sufficient
if (distanceTime1.back().distance >= D || distanceTime2.back().distance >= D) {
return true;
}
// Merge both lists
for (auto e1 : distanceTime1) {
// Binary search in second list
int a = 0;
int b = distanceTime2.size() - 1;
while (a != b) {
int middle = (a + b + 1) / 2;
auto e2 = distanceTime2[middle];
if (e1.time + e2.time < T) {
a = middle;
} else {
b = middle - 1;
}
}
auto e2 = distanceTime2[a];
// The combination is feasible
if (e1.time + e2.time < T && e1.distance + e2.distance >= D) {
return true;
}
}
return false;
}
void solve() {
cin >> n >> m >> D >> T;
d = vector<long>(n);
t = vector<long>(n);
for (int i = 0; i < n; ++i) {
cin >> d[i] >> t[i];
}
s = vector<long>(m + 2);
for (int i = 1; i <= m; ++i) {
cin >> s[i];
}
// Binary search over number of gulps
int a = 0;
int b = m + 1;
while (a != b) {
int gulps = (a + b) / 2;
if (isFeasible(gulps)) {
b = gulps;
}
else {
a = gulps + 1;
}
}
if (a == m + 1) {
cout << "Panoramix captured" << endl;
}
else {
cout << a << endl;
}
}
int main() {
ios_base::sync_with_stdio(false);
int t; cin >> t;
for (int i = 0; i < t; ++i) {
solve();
}
}