namespace nilrider { void level::solve() { ld xunit = .25, yunit = .25, eunit = xunit * yunit / 2; struct edge { int id; int dz; ld zval1; ld length; }; struct vertex { int id; int x, y; ld zval; hyperpoint where; bool goal; map > > visited; vector edges; }; map, int> xy_to_id; vector vertices; auto getpt = [&] (int x, int y) { hyperpoint p = point31(start.where[0] + x * xunit, start.where[1] + y * yunit, 0); p[2] = surface(p); return p; }; auto get_id = [&] (int x, int y) { if(xy_to_id.count({x, y})) return xy_to_id[{x, y}]; else { int id = isize(vertices); xy_to_id[{x,y}] = id; vertices.emplace_back(); auto& b = vertices.back(); b.where = getpt(x, y); b.id = id; b.x = x; b.y = y; return id; } }; get_id(0, 0); transmatrix Rstart = gpushxto0(vertices[0].where); for(int id=0; id > > dijkstra_queue; auto visit = [&] (ld nt, int id, int z, int bid, int bz) { auto& t = vertices[id].visited[z]; if(t.first == 0 || t.first > nt) { t.first = nt; t.second = {bid, bz}; pair > d = {-nt, {id, z}}; dijkstra_queue.emplace(d); } }; visit(1e-15, 0, 0, 0, 0); /* more than 0 to mark it */ // h[0] * h[1] / 2 yields 0 int step = 0; while(!dijkstra_queue.empty()) { auto q = dijkstra_queue.top(); dijkstra_queue.pop(); ld t0 = -q.first; int id0 = q.second.first; int z0 = q.second.second; auto& v = vertices[id0]; if(step % 10000 == 0) println(hlog, t0, " : ", tie(id0, z0), " edges = ", isize(v.edges)); step++; if(v.goal) { println(hlog, "reached the goal in time ", t0); vector positions; while(id0 || z0) { println(hlog, "z = ", z0); positions.emplace_back(vertices[id0].where); auto& b = vertices[id0].visited[z0]; id0 = b.second.first; z0 = b.second.second; } positions.emplace_back(vertices[0].where); reverse(positions.begin(), positions.end()); println(hlog, positions); plan.clear(); for(auto pos: positions) { plan.emplace_back(pos, hpxy(0, 0)); } return; } for(auto& e: v.edges) { int z1 = z0 + e.dz; ld energy0 = z0 * eunit - v.zval; ld energy1 = z1 * eunit - e.zval1; if(energy0 < -1e-6) continue; if(energy0 < 0) energy0 = 0; if(energy1 < -1e-6) continue; if(energy1 < 0) energy1 = 0; ld t1 = t0 + e.length / (sqrt(energy0) + sqrt(energy1)); visit(t1, e.id, z1, id0, z0); } // exit(1); } println(hlog, "failed to reach the goal!"); exit(1); } }