제출 #843672

#제출 시각아이디문제언어결과실행 시간메모리
843672TranGiaHuy1508로봇 대회 (IOI23_robot)C++17
0 / 100
105 ms8880 KiB
#include <bits/stdc++.h> using namespace std; #include "robot.h" enum State { BOUNDARY = -2, OBSTACLE = -1, EMPTY = 0, MAIN = 1, WEST = 2, SOUTH = 3, EAST = 4, NORTH = 5, CLEANING = 6, EVERYTHING = -42, BLOCKED = -3, DIRECTIONS = -4, ENDING = -5, }; enum Move { M_STAY = 'H', M_WEST = 'W', M_SOUTH = 'S', M_EAST = 'E', M_NORTH = 'N', M_TERMINATE = 'T', }; State clockwise(State S){ if (S == NORTH) return EAST; if (S == EAST) return SOUTH; if (S == SOUTH) return WEST; if (S == WEST) return NORTH; return S; } State opposite(State S){ return clockwise(clockwise(S)); } State counter_clockwise(State S){ return clockwise(opposite(S)); } int dir_idx(State S){ assert(S >= 2 && S <= 5); return S - 1; } Move with_dir(State S){ if (S == WEST) return M_WEST; if (S == SOUTH) return M_SOUTH; if (S == EAST) return M_EAST; if (S == NORTH) return M_NORTH; assert((false)); } namespace Script { static const int arrLen = 5; using StateArray = array<State, arrLen>; using Instruction = pair<State, Move>; map<StateArray, Instruction> mp; // Helper functions StateArray everything(){ StateArray res; for (int i = 0; i < arrLen; i++) res[i] = EVERYTHING; return res; } vector<State> group(State S){ if (S == BLOCKED) return {BOUNDARY, OBSTACLE}; if (S == DIRECTIONS) return {WEST, SOUTH, EAST, NORTH}; if (S == ENDING) return {MAIN, BOUNDARY, OBSTACLE}; if (S == EVERYTHING) return { BOUNDARY, OBSTACLE, EMPTY, MAIN, CLEANING, WEST, SOUTH, EAST, NORTH }; return {S}; } template <bool OVERWRITE = false> void program(StateArray S, Instruction I){ vector<StateArray> arrs = {StateArray()}; // Construct all possible StateArray(s) for (int i = 0; i < arrLen; i++){ vector<StateArray> new_arrs; vector<State> repr = group(S[i]); for (auto arr: arrs){ for (auto j: repr){ new_arrs.push_back(arr); new_arrs.back()[i] = j; } } new_arrs.swap(arrs); } // Resolve for (auto arr: arrs){ if (!OVERWRITE && mp.count(arr)) continue; mp[arr] = I; } } template <bool OVERWRITE = false> void program(StateArray S, State Z, Move A){ return program<OVERWRITE>(S, {Z, A}); } void set_all_instruction(){ for (auto [S, I]: mp){ vector<int> vS(begin(S), begin(S) + arrLen); set_instruction(vS, I.first, I.second); } } } void main_program(); void program_pulibot(){ main_program(); Script::set_all_instruction(); } void main_program(){ // Starting position Script::program<true>({ EMPTY, BOUNDARY, EVERYTHING, EVERYTHING, BOUNDARY }, NORTH, M_STAY); // Move forward for (State crr: Script::group(DIRECTIONS)){ State nxt = clockwise(crr); Script::StateArray arr = Script::everything(); arr[0] = crr; // Move to everything Script::program<false>(arr, nxt, M_STAY); // Move to empty square arr[dir_idx(nxt)] = EMPTY; Script::program<true>(arr, nxt, with_dir(nxt)); // Move to child square arr[dir_idx(nxt)] = opposite(nxt); Script::program<true>(arr, nxt, with_dir(nxt)); } // Empty square for (State indir: Script::group(DIRECTIONS)){ Script::StateArray arr = Script::everything(); arr[0] = EMPTY; arr[dir_idx(indir)] = opposite(indir); Script::program<false>(arr, indir, with_dir(indir)); // If this is (H-1, W-1), mark as MAIN instead if (indir != EAST && indir != SOUTH){ arr[dir_idx(EAST)] = BOUNDARY; arr[dir_idx(SOUTH)] = BOUNDARY; // Script::program<true>(arr, MAIN, with_dir(indir)); Script::program<true>(arr, CLEANING, with_dir(indir)); } } // If pointing to MAIN/CLEANING, mark as CLEANING for (State dir: Script::group(DIRECTIONS)){ Script::StateArray arr = Script::everything(); arr[0] = dir; arr[dir_idx(dir)] = MAIN; Script::program<true>(arr, CLEANING, M_STAY); arr[dir_idx(dir)] = CLEANING; Script::program<true>(arr, CLEANING, M_STAY); } // If currently CLEANING, and there is nothing to clean for (State dir: Script::group(DIRECTIONS)){ Script::StateArray arr = Script::everything(); arr[0] = CLEANING; // Moving to MAIN arr[dir_idx(dir)] = MAIN; Script::program<false>(arr, MAIN, with_dir(dir)); // Moving to CLEANING arr[dir_idx(dir)] = CLEANING; Script::program<true>(arr, EMPTY, with_dir(dir)); Script::StateArray tmparr = arr; // If there is a MAIN, change color to MAIN instead for (State maindir: Script::group(DIRECTIONS)){ if (maindir == dir) continue; tmparr[dir_idx(maindir)] = MAIN; Script::program<true>(tmparr, MAIN, with_dir(dir)); tmparr = arr; } arr = Script::everything(); arr[0] = CLEANING; // If at start arr[dir_idx(NORTH)] = BOUNDARY; arr[dir_idx(WEST)] = BOUNDARY; if (dir != NORTH && dir != WEST){ arr[dir_idx(dir)] = CLEANING; Script::program<true>(arr, MAIN, with_dir(dir)); arr[dir_idx(dir)] = MAIN; Script::program<true>(arr, MAIN, with_dir(dir)); } } // If currently CLEANING, and there is a path to clean for (State indir: Script::group(DIRECTIONS)){ Script::StateArray arr = Script::everything(); arr[0] = CLEANING; arr[dir_idx(indir)] = opposite(indir); Script::program<true>(arr, CLEANING, with_dir(indir)); } // Termination Script::program<true>({ MAIN, MAIN, BOUNDARY, BOUNDARY, EVERYTHING }, MAIN, M_TERMINATE); Script::program<true>({ MAIN, EVERYTHING, BOUNDARY, BOUNDARY, MAIN }, MAIN, M_TERMINATE); Script::program<true>({ MAIN, ENDING, ENDING, ENDING, ENDING }, MAIN, M_TERMINATE); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...