Skip to content

Commit 1ce2360

Browse files
author
nschweitzer
committed
astar
1 parent c5fae75 commit 1ce2360

File tree

6 files changed

+1026
-350
lines changed

6 files changed

+1026
-350
lines changed

.clang-format

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
BasedOnStyle: Google
2+
# Two below options to be used with patched version of clang-format, otherwise set false
23
BinPackArguments: false
34
BinPackParameters: false
45
ColumnLimit: 120
56
DerivePointerAlignment: false
67
PointerAlignment: Right
8+
Standard: Cpp03

CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,4 @@ add_executable(${PROJECT_NAME}_tins "puzzle/thereIsNoSpoon2.cpp")
55
add_executable(${PROJECT_NAME}_hs "contest/hypersonic.cpp")
66
add_executable(${PROJECT_NAME}_fb "contest/fantasticBits.cpp")
77
add_executable(${PROJECT_NAME}_gitc "contest/gostInTheCell.cpp")
8-
add_executable(${PROJECT_NAME}_u16 "contest/unleash16.cpp")
9-
add_executable(${PROJECT_NAME}_u17 "contest/unleash17.cpp")
108
add_executable(${PROJECT_NAME}_ww "contest/wondevwoman.cpp")

contest/astart.cpp

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
#pragma GCC target("avx") // small optimization
2+
#pragma GCC optimize("O3") // +44k killer optimization with "inline __attribute__ (( always_inline,
3+
// visibility("protected") ))" and "inline"
4+
#pragma GCC optimize("omit-frame-pointer") // good optimization
5+
#pragma GCC optimize("unsafe-math-optimizations") // not really useful it seems
6+
#pragma GCC optimize("unroll-all-loops") // good optimization
7+
#pragma GCC optimize("inline") // killer optimization with O3
8+
9+
#include <stdlib.h>
10+
#include <string.h>
11+
#include <algorithm>
12+
#include <array>
13+
#include <bitset>
14+
#include <cassert>
15+
#include <chrono>
16+
#include <climits>
17+
#include <cmath>
18+
#include <deque>
19+
#include <fstream>
20+
#include <iostream>
21+
#include <limits>
22+
#include <list>
23+
#include <map>
24+
#include <queue>
25+
#include <random>
26+
#include <set>
27+
#include <sstream>
28+
#include <string>
29+
#include <tuple>
30+
#include <unordered_map>
31+
#include <unordered_set>
32+
#include <vector>
33+
34+
using namespace std;
35+
36+
string dir("URDL");
37+
map<char, int> mdir = {{'U', 0}, {'R', 1}, {'D', 2}, {'L', 3}};
38+
/*
39+
0
40+
U, R, D, L
41+
UR, RD, DL, LU, UD, RL
42+
URD, RDL, DLU, LUR
43+
URDL
44+
*/
45+
#define UP (1 << 0)
46+
#define RIGHT (1 << 1)
47+
#define DOWN (1 << 2)
48+
#define LEFT (1 << 3)
49+
50+
array<string, 16> possible = {
51+
" ", "U ", "R ", "UR ", "D ", "UD ", "RD ", "URD ", "L ", "LU ", "RL ", "LUR ", "DL ", "DLU ", "RDL ", "URLD "};
52+
53+
#define HALF_TIME (200)
54+
#define TIME_MAX (980)
55+
56+
struct Timer {
57+
chrono::time_point<chrono::system_clock> start;
58+
chrono::time_point<chrono::system_clock> end;
59+
chrono::time_point<chrono::system_clock> half;
60+
signed char not_always = 0;
61+
62+
inline Timer(Timer const &) = default;
63+
inline Timer(Timer &&) = default;
64+
inline Timer &operator=(Timer const &) = default;
65+
inline Timer &operator=(Timer &&) = default;
66+
67+
inline Timer() {
68+
this->start = chrono::system_clock::now();
69+
this->end = chrono::system_clock::now() + chrono::milliseconds(TIME_MAX);
70+
this->half = chrono::system_clock::now() + chrono::milliseconds(HALF_TIME);
71+
}
72+
inline long long click() const {
73+
return chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - this->start).count();
74+
}
75+
inline bool timesUp() { return std::chrono::system_clock::now() > this->end; }
76+
inline bool halfTime() { return std::chrono::system_clock::now() > this->half; }
77+
};
78+
79+
struct Pos {
80+
int i, x, y;
81+
inline Pos() = default;
82+
inline Pos(int x, int y) : i(0), x(x), y(y) {}
83+
inline Pos(int i, int x, int y) : i(i), x(x), y(y) {}
84+
inline Pos(Pos const &) = default;
85+
inline Pos(Pos &&) = default;
86+
inline Pos &operator=(Pos const &) = default;
87+
inline Pos &operator=(Pos &&) = default;
88+
89+
int dist(const Pos &p) { return abs(this->x - p.x) + abs(this->y - p.y); }
90+
91+
int dist1(const Pos &p) { return (this->x - p.x) * (this->x - p.x) + (this->y - p.y) * (this->y - p.y); }
92+
93+
double dist2(const Pos &p) { return sqrt(dist1(p)); }
94+
95+
void norm() {
96+
x = x / sqrt(x * x + y * y);
97+
y = y / sqrt(x * x + y * y);
98+
}
99+
100+
int scalar(const Pos &p) { return this->x * p.x + this->y * p.y; }
101+
102+
Pos move(const Pos &p) { return Pos(x - (x - p.x) * 60.0 / this->dist2(p), y - (y - p.y) * 60.0 / this->dist2(p)); }
103+
104+
bool isInRange(Pos p, double range) { return p != *this && dist2(p) <= range; }
105+
106+
inline bool operator==(const Pos &c) const { return this->x == c.x and this->y == c.y and this->i == c.i; }
107+
inline bool operator!=(const Pos &c) const { return !((*this) == c); }
108+
inline bool operator<(const Pos &c) const { return this->x + 100 * this->y < c.x + 100 * c.y; }
109+
inline Pos operator+(const Pos &c) const { return Pos(this->x + c.x, this->y + c.y); }
110+
inline Pos operator-(const Pos &c) const { return Pos(this->x - c.x, this->y - c.y); }
111+
inline Pos operator*(const int &c) const { return Pos(this->x * c, this->y * c); }
112+
inline Pos operator/(const int &c) const { return Pos(this->x / c, this->y / c); }
113+
virtual void serialize(ostream &os) const { os << i << " [" << x << "," << y << "] "; }
114+
};
115+
ostream &operator<<(ostream &os, const Pos &c) {
116+
c.serialize(os);
117+
return os;
118+
}
119+
120+
struct Robo : public Pos {
121+
char d;
122+
inline Robo() = default;
123+
inline Robo(int x, int y) : Pos(x, y), d('U') {}
124+
inline Robo(int x, int y, char d) : Pos(x, y), d(d) {}
125+
inline Robo(int i, int x, int y, char d) : Pos(i, x, y), d(d) {}
126+
inline Robo(Robo const &) = default;
127+
inline Robo(Robo &&) = default;
128+
inline Robo &operator=(Robo const &) = default;
129+
inline Robo &operator=(Robo &&) = default;
130+
131+
inline bool operator==(const Robo &c) const {
132+
return this->x == c.x and this->y == c.y and this->i == c.i and this->d == c.d;
133+
}
134+
inline bool operator!=(const Robo &c) const { return !((*this) == c); }
135+
inline bool operator<(const Robo &c) const { return this->x + 100 * this->y < c.x + 100 * c.y; }
136+
inline Robo operator+(const Robo &c) const { return Robo(this->x + c.x, this->y + c.y); }
137+
inline Robo operator-(const Robo &c) const { return Robo(this->x - c.x, this->y - c.y); }
138+
inline Robo operator*(const int &c) const { return Robo(this->x * c, this->y * c); }
139+
inline Robo operator/(const int &c) const { return Robo(this->x / c, this->y / c); }
140+
};
141+
142+
namespace std {
143+
template <>
144+
struct hash<Pos> {
145+
inline size_t operator()(const Pos &p) const { return p.x * 1812433253 + p.y; }
146+
};
147+
template <>
148+
struct hash<Robo> {
149+
inline size_t operator()(const Robo &p) const { return p.x * 1812433253 + p.y; }
150+
};
151+
} // namespace std
152+
153+
struct Grid {
154+
static array<Robo, 4> axis;
155+
156+
int width, height;
157+
unordered_set<Pos> walls;
158+
unordered_set<Pos> cells;
159+
unordered_map<Pos, char> items;
160+
161+
Grid() {}
162+
Grid(int width_, int height_) : width(width_), height(height_) {}
163+
inline Grid(Grid const &) = default;
164+
inline Grid(Grid &&) = default;
165+
166+
inline bool isWall(Pos id) const { return walls.count(id); }
167+
inline bool isCell(Pos id) const { return cells.count(id); }
168+
inline bool isItem(Pos id) const { return items.count(id); }
169+
170+
inline int remap(int i, int t) const {
171+
if (i == t)
172+
return 0;
173+
else if (i == -1)
174+
return t - 1;
175+
else
176+
return i;
177+
}
178+
179+
unsigned int cellType(const Pos &r) const {
180+
unsigned int cell(0);
181+
for (int i(0); i < 4; ++i) {
182+
Pos next(remap(r.x + axis[i].x, width), remap(r.y + axis[i].y, height));
183+
if (!isWall(next)) cell += 1 << i;
184+
}
185+
return cell;
186+
}
187+
};
188+
array<Robo, 4> Grid::axis{Robo{0, -1}, Robo{1, 0}, Robo{0, 1}, Robo{-1, 0}};
189+
190+
struct Board {
191+
Grid g = Grid(19, 10);
192+
int nbRobo, maxScore;
193+
array<Robo, 10> robos;
194+
vector<vector<Robo> > Actions;
195+
vector<Robo> best;
196+
197+
void init() {
198+
for (int j = 0; j < 10; ++j) {
199+
string line;
200+
cin >> line;
201+
cin.ignore();
202+
for (int i(0); i < line.size(); ++i) {
203+
switch (line[i]) {
204+
case '#':
205+
g.walls.insert(Pos(i, j));
206+
break;
207+
case 'U':
208+
case 'D':
209+
case 'L':
210+
case 'R':
211+
case 'u':
212+
case 'd':
213+
case 'l':
214+
case 'r':
215+
g.items[Robo(i, j)] = toupper(line[i]);
216+
break;
217+
case '.':
218+
g.cells.insert(Pos(i, j));
219+
}
220+
}
221+
}
222+
cin >> nbRobo;
223+
cin.ignore();
224+
for (int i = 0; i < nbRobo; ++i) {
225+
cin >> robos[i].x >> robos[i].y >> robos[i].d;
226+
cin.ignore();
227+
}
228+
}
229+
230+
Robo nextPos(const Robo &r) {
231+
auto i = g.items.find(r);
232+
if (i != g.items.end() and i->second != ' ') {
233+
// cerr << r.x << " " << r.y << " in items" << endl;
234+
Robo n = Robo(r + g.axis[mdir[i->second]]);
235+
n.x = g.remap(n.x, g.width);
236+
n.y = g.remap(n.y, g.height);
237+
n.d = i->second;
238+
return n;
239+
} else {
240+
Robo n = Robo(r + g.axis[mdir[r.d]]);
241+
n.d = r.d;
242+
n.x = g.remap(n.x, g.width);
243+
n.y = g.remap(n.y, g.height);
244+
// cerr << r.d << " " << mdir[r.d] << " " << g.axis[mdir[r.d]] << endl;
245+
return n;
246+
}
247+
return r;
248+
}
249+
250+
int walk(const Robo &r) {
251+
int score(0);
252+
unordered_set<Robo> states;
253+
Robo next = Robo(r.x, r.y, r.d);
254+
// cerr << "init " << next.x << " " << next.y << " " << next.d << endl;
255+
while (!g.isWall(next)) {
256+
next = nextPos(next);
257+
if (states.count(next)) break;
258+
states.insert(next);
259+
++score;
260+
// cerr << states.count(next) << " " << next.x << " " << next.y << endl;
261+
}
262+
// cerr << "final " << next.x << " " << next.y << " " << next.d << endl;
263+
return score;
264+
}
265+
266+
vector<Pos> strategicCells() {
267+
vector<Pos> k;
268+
for (auto c : g.cells) {
269+
// cerr << c.x << " " << c.y << " " << g.cellType(c) << endl;
270+
if (g.cellType(c) != 5 and g.cellType(c) != 10 and g.cellType(c) != 0) k.push_back(c);
271+
}
272+
return k;
273+
}
274+
275+
void allActions(const vector<Pos> &k, vector<Robo> &combi, int n, Timer theClock) {
276+
if (theClock.halfTime()) return;
277+
if (n == k.size() - 1) {
278+
for (auto c : possible[g.cellType(k[n])]) {
279+
// cerr << k[n].x << "-" << k[n].y << " " << c << " " << g.cellType(k[n]) << endl;
280+
combi.push_back(Robo(k[n].x, k[n].y, c));
281+
Actions.push_back(combi);
282+
combi.pop_back();
283+
}
284+
} else {
285+
for (auto c : possible[g.cellType(k[n])]) {
286+
// cerr << k[n].x << "+" << k[n].y << " " << c << " " << g.cellType(k[n]) << endl;
287+
combi.push_back(Robo(k[n].x, k[n].y, c));
288+
allActions(k, combi, n + 1, theClock);
289+
combi.pop_back();
290+
}
291+
}
292+
}
293+
294+
string printCombi(vector<Robo> r) {
295+
string s("");
296+
for (auto c : r) s += to_string(c.x) + "," + to_string(c.y) + "|" + c.d + "-";
297+
return s;
298+
}
299+
300+
int play(Timer theClock) {
301+
int played(0);
302+
cerr << Actions.size() << endl;
303+
for (auto combis : Actions) {
304+
if (theClock.timesUp()) return played;
305+
for (auto item : combis) g.items[item] = item.d;
306+
307+
int s(0);
308+
for (int i(0); i < nbRobo; ++i) s += walk(robos[i]);
309+
// cerr << "# " << combis.size() << " pt " << s << " " << printCombi(combis) << endl;
310+
if (s >= maxScore) {
311+
maxScore = s;
312+
best = combis;
313+
}
314+
for (auto item : combis) g.items.erase(item);
315+
++played;
316+
}
317+
return played;
318+
}
319+
320+
void writeResult() const {
321+
string out("");
322+
// cerr << best.size() << " " << maxScore << endl;
323+
for (auto e : best) {
324+
if (e.d != ' ') out += to_string(e.x) + " " + to_string(e.y) + " " + e.d + " ";
325+
}
326+
cout << out << endl;
327+
}
328+
};
329+
330+
int main() {
331+
Board b = Board();
332+
b.init();
333+
Timer theClock;
334+
vector<Pos> cells = b.strategicCells();
335+
vector<Robo> combi;
336+
b.allActions(cells, combi, 0, theClock);
337+
cerr << "actions " << theClock.click() << endl;
338+
int played = b.play(theClock);
339+
cerr << " play " << theClock.click() << " / " << played << endl;
340+
b.writeResult();
341+
}

0 commit comments

Comments
 (0)