#include /*{{{*/ #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;/*}}}*/ // #define DBG(x) {x} #ifndef DBG #define DBG(x) #endif enum JudgeCode:int{ judge_error=1, correct=42, wrong_answer=43, }; namespace limits{ constexpr int64_t moves_max=20ll; // 20 constexpr int64_t blocks_max=10ll*1000; // 10^4 constexpr int64_t border_radius=1ll*1000*1000*1000+1; // 10^9 } struct Vec2{/*{{{*/ int64_t x; int64_t y; explicit Vec2(int64_t x,int64_t y,JudgeCode const on_fail): x(x), y(y){ if (abs(x)>=limits::border_radius or abs(y)>=limits::border_radius){ cout<<"Vector out of bounds: "< const moves; map> block_rows; map> block_cols; public: Solution(vector const &moves,vector const &blocks): moves(moves){ DBG(cerr<<"imported blocks"<second.begin(),it->second.end(),block.x); } Vec2 simulate(Vec2 const ball,Vec2 const dir) const{ if (has_block(ball)){ return ball; } if (dir.y==0){ return Vec2( dir.x>0 ? find_next(block_rows, ball.y, ball.x, +limits::border_radius)-1 : find_prev(block_rows, ball.y, ball.x, -limits::border_radius)+1, ball.y, judge_error); }else{ return Vec2( ball.x, dir.y>0 ? find_next(block_cols, ball.x, ball.y, +limits::border_radius)-1 : find_prev(block_cols, ball.x, ball.y, -limits::border_radius)+1, judge_error); } } int64_t find_next( map> const &rows, int64_t const y, int64_t const x, int64_t const limit) const{ auto const it=rows.find(y); if (it==rows.end() or it->second.empty() or it->second.back()second.begin(),it->second.end(),x); } int64_t find_prev( map> const &rows, int64_t const y, int64_t const x, int64_t const limit) const{ auto const it=rows.find(y); if (it==rows.end() or it->second.empty() or it->second[0]>x){ return limit; } return *--lower_bound(it->second.begin(),it->second.end(),x); } public: bool validate(Vec2 const start, JudgeCode const on_fail) const{ if (has_block(start)){ cout<<"Ball starts inside a block"< places={start}; cout<<" start: ("< read_blocks(istream &source,JudgeCode const on_fail){/*{{{*/ int64_t n; source>>n; if (n<0 or limits::blocks_max blocks; for (int64_t i=0; i>x>>y)){ cout<<"Failed to read x and y coordinates"<> dummy) { cout<<"trailing output"< const &moves, JudgeCode const on_fail){ // Read starting location of ball. int64_t ball_x,ball_y;{ stringstream sst(first_word); if (not (sst>>ball_x)){ cout<>ball_y)){ cout<4){ cerr<<"warning: ignoring "<>moves_str)){ cout<<"Failed to read moves from input"< moves; for (auto i: moves_str) { switch (i){ case 'U': moves.push_back(Vec2{0,+1,judge_error}); break; case 'D': moves.push_back(Vec2{0,-1,judge_error}); break; case 'R': moves.push_back(Vec2{+1,0,judge_error}); break; case 'L': moves.push_back(Vec2{-1,0,judge_error}); break; default:{ cout<<"Character '"<>canonical_answer)){ cout<<"Canonical output is empty"<>team_answer)){ cout<<"Team failed to print anything"<> dummy) { cout<<"trailing output after impossible"<