Submission #1220962

#TimeUsernameProblemLanguageResultExecution timeMemory
1220962madamadam3Robot Contest (IOI23_robot)C++20
26 / 100
77 ms5972 KiB
#include "robot.h" #include <bits/stdc++.h> using namespace std; /* boundary: state = -2 obstacle: state = -1 otherwise: state = colour n = up, s = down, w = left, e = right S[0] is the state of cell (r, c). S[1] is the state of the cell to the west. S[2] is the state of the cell to the south. S[3] is the state of the cell to the east. S[4] is the state of the cell to the north. */ set<string> instr; void instruction(vector<int> S, int Z, char A, bool ignore_duplicate = false) { string val = ""; for (auto &el : S) val += to_string(el); if (instr.count(val) && !ignore_duplicate) { // cout << "Duplicate with: \n"; // cout << val << "\n"; } else { if (!instr.count(val)) set_instruction(S, Z, A); instr.insert(val); } } void solve_empty() { // if its entirely empty: go right while not a border on the right, then go up // if instruction({0, -2, 0, 0, -2}, 1, 'E'); // at (0, 0): go right instruction({0, 1, 0, 0, -2}, 1, 'E'); // travelling along bottom: go right instruction({0, 1, 0, -2, -2}, 1, 'S'); // at (W, 0): go down instruction({0, 0, 0, -2, 1}, 1, 'S'); // travelling along side: go down instruction({0, 0, -2, -2, 1}, 1, 'T'); // at (W, H): terminate } void solve_h2() { // while possible, walk right // if not possible, go down/up // if at (W, H-1), go up // go right while possible for (auto &west_state : {-2, -1, 0, 1}) { for (auto &south_state : {-2, -1, 0, 1}) { for (auto &north_state : {-2, -1, 0, 1}) { instruction({0, west_state, south_state, 0, north_state}, 1, 'E'); } } } // go down when needed for (auto &east_state : {-2, -1}) { for (auto &west_state : {-2, 1}) { instruction({0, west_state, 0, east_state, -2}, 1, 'S'); } } // go up when needed for (auto &east_state : {-1}) { for (auto &west_state : {-2, 1}) { instruction({0, west_state, -2, east_state, 0}, 1, 'N'); } } // at end for (auto &west_state : {-2, -1, 0, 1}) { for (auto &north_state : {-1, 0, 1}) { instruction({0, west_state, -2, -2, north_state}, 1, 'T'); } } } const char DIR[5] = {'H', 'W', 'S', 'E', 'N'}; const int PERM[24][4] = { {1, 2, 3, 4}, {1, 2, 4, 3}, {1, 3, 2, 4}, {1, 3, 4, 2}, {1, 4, 2, 3}, {1, 4, 3, 2}, {2, 1, 3, 4}, {2, 1, 4, 3}, {2, 3, 1, 4}, {2, 3, 4, 1}, {2, 4, 1, 3}, {2, 4, 3, 1}, {3, 1, 2, 4}, {3, 1, 4, 2}, {3, 2, 1, 4}, {3, 2, 4, 1}, {3, 4, 1, 2}, {3, 4, 2, 1}, {4, 1, 2, 3}, {4, 1, 3, 2}, {4, 2, 1, 3}, {4, 2, 3, 1}, {4, 3, 1, 2}, {4, 3, 2, 1} }; #define wall(x) for (auto &x : {-2, -1}) #define wall_or_empty(x) for (auto &x : {-1, 0, 4}) #define wempty(x) for (auto &x : {-1, 0}) #define EBX(x) for (auto &x : {0, -1, -2, 4}) #define any(x) for (auto &x : {-2, -1, 0, 1, 2, 3, 4, 5}) #define empty_blue(x) for (auto &x : {0, 1}) #define bygo(x) for (auto &x : {1, 2, 3, 4, 5}) #define yg(x) for (auto &x : {1, 2}) #define ygo(x) for (auto &x : {2,3,4, 5}) #define RE(x) for (auto &x : {0, 4}) #define rwall(x) for (auto &x : {-1, -2, 4}) #define ewall(x) for (auto &x : {-1, -2, 0}) void rotate(vector<int> S, int Z, int C) { set<string> seen; for (auto &perm : PERM) { vector<int> ins(5); ins[0] = S[0]; ins[perm[0]] = S[1]; ins[perm[1]] = S[2]; ins[perm[2]] = S[3]; ins[perm[3]] = S[4]; char dir; if (C == 0) dir = 'T'; else if (C == 5) dir = 'H'; else dir = DIR[perm[C-1]]; string v = ""; for (auto &el : ins) v+=to_string(el); if (seen.count(v)) continue; seen.insert(v); instruction(ins, Z, dir); } } void corners() { // (1) special cases for the corners // (a) 0, 0 instruction({0, -2, -1, 0, -2}, 1, 'E'); // only right instruction({0, -2, 0, -1, -2}, 1, 'S'); // only down instruction({0, -2, 0, 0, -2}, 2, 'E'); // both options, go right instruction({2, -2, 0, 0, -2}, 1, 'S'); // option 1 bad, go down instruction({2, -2, 0, 1, -2}, 1, 'T'); // option 1 good, make blue and terminate instruction({2, -2, 1, 0, -2}, 1, 'T'); // option 2 good, make blue and terminate // (b) (W, 0) or (0, W) bygo(col) { // keep the colour, going down or right instruction({0, col, 0, -2, -2}, col, DIR[2]); instruction({0, 0, col, -2, -2}, col, DIR[1]); instruction({0, -2, -2, col, 0}, col, DIR[4]); instruction({0, -2, -2, 0, col}, col, DIR[3]); // reverse a yellow // if (col == 1) continue; // go in opposite direction if we have a blue // instruction({3, col, 1, -2, -2}, 1, DIR[1]); // instruction({3, 1, col, -2, -2}, 1, DIR[2]); // instruction({3, -2, -2, col, 1}, 1, DIR[3]); // instruction({3, -2, -2, 1, col}, 1, DIR[4]); wall_or_empty(a) { instruction({0, col, a, -2, -2}, 0, DIR[1]); instruction({0, a, col, -2, -2}, 0, DIR[2]); instruction({3, col, a, -2, -2}, 0, DIR[1]); instruction({3, a, col, -2, -2}, 0, DIR[2]); instruction({0, -2, -2, col, a}, 0, DIR[3]); instruction({0, -2, -2, a, col}, 0, DIR[4]); instruction({3, -2, -2, col, a}, 0, DIR[3]); instruction({3, -2, -2, a, col}, 0, DIR[4]); } } // (c) (W, H) wall_or_empty(c) { // we can end instruction({0, c, -2, -2, 1}, 1, 'T'); instruction({0, 1, -2, -2, c}, 1, 'T'); ygo(c2) { // need to go back instruction({0, c, -2, -2, c2}, 1, DIR[4]); instruction({0, c2, -2, -2, c}, 1, DIR[1]); } } } void forced_movements() { // (2) we are carrying the previous colour with us to the only empty square we have wall(a) { rotate({0, a, -1, 0, 1}, 1, 3); ygo(b) rotate({0, a, -1, 0, b}, 3, 3); } } void clean_to_green() { // or orange // (3) undoing a forward movement with yellow colour to clean it wall(a) ygo(b) rotate({3, a, -1, b, 0}, 0, 3); // case 1: cleaning the yellow colour wall(a) ygo(b) rotate({3, a, -1, b, 1}, 1, 3); // case 2: found the answer we're setting everything blue until we reach green/orange } void dead_ends() { // (4) we hit a dead end in our search down a branch wall(a) { ygo(b) rotate({0, a, -1, -1, b}, 0, 4); } } void blue2branch() { // (5) our parent is blue, but we have 2 children wall(a) rotate({0, a, 1, 0, 0}, 2, 4); // case 1: we just arrived, so set to green and go down child 1 wall(a) rotate({2, a, 1, 1, 0}, 1, 0); // case 2: we've come back from child 1 and child 1 is blue (we found the shortest path) wall(a) rotate({2, a, 1, 0, 0}, 1, 3); // case 3: come back from child 1, and it doesnt lead to the answer } void blue3branch() { // (6) our parent is blue, but we have 3 children rotate({0, 1, 0, 0, 0}, 2, 4); // case 1: just arrived, go down first preference rotate({2, 1, 1, 0, 0}, 1, 0); // case 2: first preference good, set to blue and terminate rotate({2, 1, 0, 0, 0}, 4, 3); // case 3: first path was bad, going down second path rotate({4, 1, 1, 0, 0}, 1, 0); // case 4: second path good, terminating rotate({4, 1, 0, 0, 0}, 1, 2); // case 5: second path bad, going down third path } void yellow2branch() { // (7) our parent is yellow/orange/green, but we have 2 children ygo(p) { wall(a) rotate({0, a, p, 0, 0}, 2, 4); // case 1: we just arrived, so set to green and go down child 1 wall(a) rotate({2, a, p, 1, 0}, 1, 2); // case 2: we've come back from child 1 and child 1 is blue (we found the shortest path) wall(a) rotate({2, a, p, 0, 0}, 4, 3); // case 3: come back from child 1, and it doesnt lead to the answer, so set to orange and go down 2 wall(a) rotate({4, a, p, 1, 0}, 1, 2); // case 4: come back from child 2, and it is the answer wall(a) rotate({4, a, p, 0, 0}, 0, 2); // case 5: come back from child 2, and it isnt the answer } } void yellow3branch() { // (8) our parent is yellow/green/orange, but we have 3 children ygo(p) { rotate({0, p, 0, 0, 0}, 2, 4); // case 1: just arrived, go down first preference rotate({2, p, 1, 0, 0}, 1, 1); // case 2: first preference good, set to blue and go to parent rotate({2, p, 0, 0, 0}, 4, 3); // case 3: first path was bad, going down second path rotate({4, p, 1, 0, 0}, 1, 1); // case 4: second path good, terminating rotate({4, p, 0, 0, 0}, 5, 2); // case 5: second path bad, going down third path rotate({5, p, 1, 0, 0}, 1, 1); // case 6: third path good: set to blue and go to parent rotate({5, p, 0, 0, 0}, 0, 1); // case 7: third path bad: set to empty and go to parent } } void solve_one_path() { // goal: simple cleaning routine (from root) corners(); forced_movements(); clean_to_green(); dead_ends(); blue2branch(); blue3branch(); yellow2branch(); yellow3branch(); } void rotate_half(vector<int> S, int Z, int C) { set<string> seen; for (auto &perm : PERM) { if ((perm[2] != 3 && perm[2] != 4) || (perm[3] != 3 && perm[3] != 4)) continue; vector<int> ins(5); ins[0] = S[0]; ins[perm[0]] = S[1]; ins[perm[1]] = S[2]; ins[perm[2]] = S[3]; ins[perm[3]] = S[4]; char dir; if (C == 0) dir = 'T'; else if (C == 5) dir = 'H'; else dir = DIR[perm[C-1]]; string v = ""; for (auto &el : ins) v+=to_string(el); if (seen.count(v)) continue; seen.insert(v); instruction(ins, Z, dir); } } // void lattice_dead() { // // dead end in a lattice means south and east are both walls // wall(a) rotate_half({}) // } void solve_lattice() { // predicated on knowing that if we find the end, and we only went right or down, we got a shortest path // every cell is a potential branchpoint /* in essence: (1) if cell empty, set to yellow and go right. (2) if cell yellow, (a) if right is blue, keep bringing the blue to the start (b) if right is empty, set to green and go down (3) if cell green, (a) if down is blue, keep bringing blue to the start (b) if down is empty, set to empty and go to parent */ // at start nicely wall_or_empty(south) instruction({3, -2, south, 1, -2}, 1, 'H'); wall_or_empty(east) instruction({2, -2, 1, east, -2}, 1, 'H'); // dead ends any(west) rwall(east) rwall(south) if (!(east == south && east == -2)) instruction({0, west, south, east, 2}, 4, 'N'); any(north) rwall(east) rwall(south) if (!(east == south && east == -2)) instruction({0, 3, south, east, north}, 4, 'W'); // at (W,H) any(west) instruction({0, west, -2, -2, 2}, 1, 'N'); any(north) instruction({0, 3, -2, -2, north}, 1, 'W'); // empty cell(s) any(west) any(north) RE(c) instruction({0, west, 0, c, north}, 2, 'S'); any(west) any(north) RE(c) instruction({0, west, 4, 0, north}, 3, 'E'); any(west) any(north) RE(c) instruction({2, west, c, 0, north}, 3, 'E'); // go down any(west) EBX(c) instruction({2, west, 1, c, 2}, 1, 'H'); any(west) EBX(c) instruction({3, west, c, 1, 2}, 1, 'H'); // bring the blue north any(west) ewall(c) instruction({1, west, 1, c, 2}, 1, 'N'); any(west) ewall(c) instruction({1, west, c, 1, 2}, 1, 'N'); // bring the blue north any(west) instruction({3, west, 4, 4, 2}, 4, 'N'); // bring the empty north any(north) EBX(c) instruction({2, 3, 1, c, north}, 1, 'H'); any(north) EBX(c) instruction({3, 3, c, 1, north}, 1, 'H'); // bring the blue west any(north) ewall(c) instruction({1, 3, 1, c, north}, 1, 'W'); any(north) ewall(c) instruction({1, 3, c, 1, north}, 1, 'W'); // bring the blue west any(north) instruction({3, 3, 4, 4, north}, 4, 'W'); // bring the empty west // walls any(west) any(north) wall(east) instruction({0, west, 0, east, north}, 2, 'S'); any(west) any(north) wall(south) instruction({0, west, south, 0, north}, 3, 'E'); any(west) wall(east) instruction({2, west, 4, east, 2}, 4, 'N'); any(north) wall(east) instruction({2, 3, 4, east, north}, 4, 'W'); any(west) wall(south) instruction({3, west, south, 4, 2}, 4, 'N'); any(north) wall(south) instruction({3, 3, south, 4, north}, 4, 'W'); // cleanup wempty(south) instruction({1, -2, south, 1, -2}, 1, 'T'); // final terminate wempty(east) instruction({1, -2, 1, east, -2}, 1, 'T'); any(west) ewall(east) ewall(south) if (!(east == south && east == -2)) instruction({4, west, south, east, 4}, 0, 'N'); any(north) ewall(east) ewall(south) if (!(east == south && east == -2) && !(north == 1)) instruction({4, 4, south, east, north}, 0, 'W'); // go down from blue any(west) any(north) instruction({1, west, 4, 1, north}, 1, 'S'); // east is blue: go down any(west) any(north) instruction({1, west, 1, 4, north}, 1, 'E'); // south is blue: go east // go up to blue ewall(south) ewall(east) any(north) instruction({4, 1, south, east, north}, 0, 'W'); // west is blue: go left ewall(south) ewall(east) any(west) instruction({4, west, south, east, 1}, 0, 'N'); // north is blue: go up // go down/right from red any(north) any(west) instruction({4, west, 4, 4, north}, 4, 'S'); any(north) any(west) ewall(east) instruction({4, west, 4, east, north}, 4, 'S'); any(north) any(west) ewall(south) instruction({4, west, south, 4, north}, 4, 'E'); } void program_pulibot() { // solve_empty(); // solve_h2(); // solve_one_path(); solve_lattice(); // solve_bfs(); }
#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...