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
|
#include <algorithm>
#include <deque>
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;
int parseID(string s) {
return (s[0] - 'A') * ('Z' - 'A' + 1) + (s[1] - 'A');
}
// Fucking hell.
struct hash_pair {
template<typename T1, typename T2>
size_t operator()(const pair<T1, T2>& p) const
{
auto h1 = hash<T1>{}(p.first);
auto h2 = hash<T1>{}(p.second);
return h1 ^ (h2 << 1);
}
};
struct Graph {
unordered_multimap<int, int> conns;
unordered_map<int, int> rates;
unordered_map<pair<int, int>, int, hash_pair> dist;
};
void findLengths(Graph &g, int base) {
deque<int> frontier;
frontier.push_back(base);
g.dist.insert({{base, base}, 0});
while (!frontier.empty()) {
// i love c++ i love c++ i love c++
int from = frontier.front();
int dist = g.dist[{base, from}];
frontier.pop_front();
auto range = g.conns.equal_range(from);
for (auto it = range.first; it != range.second; it++) {
int to = it->second;
if (g.dist.count({base, to}) != 0)
continue;
g.dist.insert({{base, to}, dist + 1});
frontier.push_back(to);
}
}
}
Graph g;
int rec(vector<int> &avail, int time1, int time2, int score = 0, int pos1 = 0, int pos2 = 0) {
int best = score;
if (time1 < time2) {
swap(time1, time2);
swap(pos1, pos2);
}
for (int i = 0; i < avail.size(); i++) {
int n = avail[i];
if (n == 0) continue;
int time1_b = time1 - g.dist[{pos1, n}] - 1;
if (time1_b > 0) {
avail[i] = 0;
int score_b = score + g.rates[n] * time1_b;
best = max(best, rec(avail, time1_b, time2, score_b, n, pos2));
avail[i] = n;
}
}
return best;
}
int main() {
vector<int> nonzero;
for (string s; getline(cin, s); ) {
auto numStart = s.find('=') + 1;
auto numEnd = s.find(';', numStart) - numStart;
int from = parseID(s.substr(6, 2));
int rate = stoi(s.substr(numStart, numEnd));
g.rates[from] = rate;
if (rate != 0) nonzero.push_back(from);
s = s.substr(s.find(' ', s.find("valve")) + 1);
for (int i = 0; i + 2 <= s.size(); i += 4) {
int to = parseID(s.substr(i, 2));
g.conns.insert({from, to});
}
}
findLengths(g, 0);
for (int base : nonzero)
findLengths(g, base);
cout << rec(nonzero, 30, 0) << endl;
cout << rec(nonzero, 26, 26) << endl;
}
|