-
Notifications
You must be signed in to change notification settings - Fork 9
/
lannister.cpp
151 lines (125 loc) · 3.26 KB
/
lannister.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
149
150
151
#include <iostream>
#include <vector>
#include <cmath>
#include <CGAL/QP_models.h>
#include <CGAL/QP_functions.h>
#include <CGAL/Gmpz.h>
typedef long IT;
typedef CGAL::Gmpz ET;
typedef CGAL::Quadratic_program<IT> Program;
typedef CGAL::Quadratic_program_solution<ET> Solution;
using namespace std;
void solve()
{
int n; // Number of nobel houses
int m; // Number of common houses
long s; // Maximum allowable sum of lengths of all sewage pipes, -1 means unbounded
cin >> n >> m >> s;
vector<int> nx(n); // x coordinates of nobel houses
vector<int> ny(n); // y coordinates of nobel houses
long nxSum = 0;
long nySum = 0;
for (int i = 0; i < n; ++i) {
cin >> nx[i] >> ny[i];
nxSum += nx[i];
nySum += ny[i];
}
vector<int> cx(m); // x coordinates of common houses
vector<int> cy(m); // y coordinates of common houses
long cxSum = 0;
long cySum = 0;
for (int i = 0; i < m; ++i) {
cin >> cx[i] >> cy[i];
cxSum += cx[i];
cySum += cy[i];
}
// Solve it as a linear program
Program lp (CGAL::SMALLER, false, 0, false, 0);
const int a = 0;
const int b = 1;
const int c = 2;
const int d = 3;
const int l = 4;
int row = 0;
// Nobel houses need to left of l1: ax + by + c
for (int i = 0; i < n; ++i) {
// ax + by + c <= 0
lp.set_a(a, row, nx[i]);
lp.set_a(b, row, ny[i]);
lp.set_a(c, row, 1);
++row;
}
// Common houses need to right of l1
for (int i = 0; i < m; ++i) {
// ax + by + c >= 0 <=> -ax -by -c <= 0
lp.set_a(a, row, -cx[i]);
lp.set_a(b, row, -cy[i]);
lp.set_a(c, row, -1);
++row;
}
// enforce a != 0 by setting a == 1
lp.set_l(a, true, 1);
lp.set_u(a, true, 1);
// Solve the LP
Solution solution = CGAL::solve_linear_program(lp, ET());
if (solution.is_infeasible()) {
cout << "Yuck!" << endl;
return;
}
// Check Tywin's constraint
// The sum of the lengths of all sewage pipes must not exceed s
if (s != -1) {
lp.set_a(b, row, cySum - nySum);
lp.set_a(c, row, m - n);
lp.set_b(row, s - (cxSum - nxSum));
row++;
solution = CGAL::solve_linear_program(lp, ET());
if (solution.is_infeasible()) {
cout << "Bankrupt!" << endl;
return;
}
}
// Jamie's optimization:
// Minimize the length l of the longest fresh water pipe
for (int i = 0; i < n; ++i) {
// length of fresh pipe <= l
lp.set_a(b, row, nx[i]);
lp.set_a(d, row, 1);
lp.set_a(l, row, -1);
lp.set_b(row, ny[i]);
row++;
lp.set_a(b, row, -nx[i]);
lp.set_a(d, row, -1);
lp.set_a(l, row, -1);
lp.set_b(row, -ny[i]);
row++;
}
for (int i = 0; i < m; ++i) {
// length of fresh pipe <= l
lp.set_a(b, row, cx[i]);
lp.set_a(d, row, 1);
lp.set_a(l, row, -1);
lp.set_b(row, cy[i]);
row++;
lp.set_a(b, row, -cx[i]);
lp.set_a(d, row, -1);
lp.set_a(l, row, -1);
lp.set_b(row, -cy[i]);
row++;
}
// Ensure l is positive
lp.set_l(l, true, 0);
// Minimize l
lp.set_c(l, 1);
solution = CGAL::solve_linear_program(lp, ET());
cout << fixed << setprecision(0) << ceil(CGAL::to_double(solution.objective_value())) << endl;
}
int main() {
ios_base::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}