void DSF(TMap const & maze, MapKeyT const & cur, MapKeyT const & prev, Cell const & target, MapT & data, vector<vector<int>> const & bonuses) { bool IsOpposite = GetOppositeDirection(prev.second) == cur.second; double to_add = (IsOpposite ? 3 : 1); if (bonuses[cur.first.m_x][cur.first.m_y] == 1) to_add -= 0.5; bool need_update = data.count(cur) == 0; need_update |= data[cur].first > data[prev].first + to_add; if (need_update) { double prev_dist = data.count(prev) == 0 ? 0 : data[prev].first; data[cur] = {prev_dist + to_add, prev}; } if (cur.first == target) return; if (need_update) { if (CanPass(maze, cur.first, cur.second)) DSF(maze, {cur.first.GetNeibor(cur.second), cur.second}, cur, target, data, bonuses); for (auto const & dir: AllDirections()) if (CanPass(maze, cur.first, dir)) DSF(maze, {cur.first.GetNeibor(dir), dir}, cur, target, data, bonuses); } }
vector<Cell> GetClosestPath(const model::World& world, Cell const & start, Direction const start_dir, Cell const & finish, Game const & game) { static map<cashe_key, vector<Cell> > cacshe; static int bonus_hash = 0; int bonus_hash_cur = 0; auto const & map = world.getTilesXY(); vector<vector<int>> bonuses(map.size(), vector<int>(map[0].size(), 0)); for (Bonus const & bonus: world.getBonuses()) { bonus_hash_cur += bonus.getX() * bonus.getX() + bonus.getY() * bonus.getY(); auto bonus_cell= GetCell(bonus, game); bonuses[bonus_cell.m_x][bonus_cell.m_y] = (bonus.getType() == PURE_SCORE || bonus.getType() == REPAIR_KIT) ? 1 : 0; } if (bonus_hash != bonus_hash_cur) { bonus_hash = bonus_hash_cur; cacshe.clear(); } cashe_key ck = {start, start_dir, finish}; if (cacshe.count(ck) == 1) return cacshe[ck]; MapT data; DSF(world.getTilesXY(), {start, start_dir}, {start, start_dir}, finish, data, bonuses); // PrintMap(world.getTilesXY(), data); vector<Cell> res; int const INF = 1000000; int best = INF; MapKeyT cur = {finish, LEFT}; for (auto dir: AllDirections()) { if (data.count({finish,dir}) == 0) continue; if (data[{finish,dir}].first < best) { best = data[{finish,dir}].first; cur = {finish,dir}; } } if (best == INF) return res; while (cur.first != start) { res.push_back(cur.first); cur = data[cur].second; } res.push_back(start); reverse(res.begin(), res.end()); cacshe[ck] = res; return res; }
std::vector<typename MapT::mapped_type> map_values(MapT const& m, KeyIterT key_first, KeyIterT key_last) { std::vector<typename MapT::mapped_type> res; while (key_first != key_last) { if (m.count(*key_first) > 0) { res.push_back(m.at(*key_first)); } ++key_first; } return res; }