題目java
機器人在形狀爲green house立方體的5個表面移動進行打掃,初始位置爲表面1上的某個給定位置,輸入一串由123組成的連續指令(1:向前移動1個單位;2:右轉方向;3:左轉方向)操做機器人,判斷最後機器人所處表面(1/2/3/4/5)。ios
細節數組
1) 當移動到當前表面邊界時執行前移操做(op=1)時會這樣移動到對應毗鄰的表面:函數
好難畫啊口區spa
2) 機器人位於表面一、二、三、4的底層邊緣時試圖往下移動的操做將會失敗,位置不變。3d
i.e.指針
輸入:N(int,立方體棱長)、location_r(int,初始位置豎直座標)、loation_c(int,初始位置水平座標)、 ops(int[200],由1/2/3組成的指令串);code
輸出:執行完全部指令後機器人所在的表面編號。對象
例子:N=4,初始位置爲3,2(注意題目的輸入以1爲起點),輸入長度25的指令1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 3, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1。blog
軌跡:
好醜啊救命
思路
[1] 把立方體表面展開並設定絕對方向;
絕對方向: 展開後的二維空間上的方向,只有上下左右4個。counterpart應該不能叫相對方向吧,反正是三維空間中根據當前所在具體平面+平面上的方向所肯定的∈R3的向量吧阿不要緊啦反正這個跟解題應該沒什麼關係
e.g. N=4,展開立方體並以表面1方向爲基準,每一個表面以左上角爲座標原點。//也能夠按別的方式展開 看我的偏好
[2] 用4個int變量grid, location_r, location_c, direction追蹤機器人每執行完一個指令後的狀態。
grid: 機器人當前所在表面編號
location_r: 機器人當前所在行座標 //我我的是以0爲起始的
location_c: 機器人當前所在列座標
direction: 機器人當前朝向 //這裏關聯前面提到的絕對方向
[3] 指令處理:可分爲 向前移動機器人 和 轉動方向
[3-1] 轉動方向
當op爲2或3的時候相應的順時針/逆時針改變方向 e.g. 當前方向爲up時,收到指令3,逆時針轉動90度因此方向更新爲left。
實現的時候能夠考慮用4個整形常量0 1 2 3標記上下左右 或者逆時針 上左下右 或者順時針 上右下左 隨便啦反正後面不要忽然弄混就是了 但我以爲這樣作可讀性不是很強,我我的偏向用枚舉enum directions{up, left, down, right}雖然考試系統的編譯器比較垃圾不認識enum因此我最後又只能默默改回用整數罷了
[3-2] 向前移動機器人
只要看當前的絕對方向是什麼再對座標作相應的更新(先無論可能會遇到座標越界須要更換所在表面的問題),e.g.direction爲up時座標r軸+=-1 c軸+=0
實現建議 上若是先前是用簡單的連續整數標記4個方向好比0/1/2/3分別表示up/left/down/right那麼能夠用一個4*2的二維數組存儲座標更新的可能delta值:deltas[4][2]={{0, -1}, {-1, 0}, {1, 0}, {0, 1}},這樣就能夠直接用方向值做爲下表獲取座標更新的delta值直接遞增在原座標上計算
固然若是題目想要再複雜一點可能一次不是隻移動一格那麼deltas裏的值也能夠改不過我也不想考慮這麼無聊的狀況了hehe
e.g.
enum directions {up, left, down, right}; int deltas[4][2]={{0, -1}, {-1, 0}, {1, 0}, {0, 1}}; //operates, change direction or move or whatever ... //get an op==1 indicates that you need to move forward location_r+=deltas[direction][0]; location_c+=deltas[direction][1];
若是更新後的座標值是合法的 i.e. 在0和N-1之間 (固然若是是從1起始就是在1和N之間啊我爲何要打這些廢話)那就完了
若是更新後的座標值不合法說明它可能要移動到另外一個平面 或者 試圖移動到最底下那個不能到達的平面但沒有成功,那就要對座標值進行再次更新使它合法,有時候方向也要根據狀況進行更新。
[3-2-2] 合法化非法座標 //聽起來爲何這麼詭異
根據以前的展開圖找規律進行相應變動
e.g. 當在表面5時location_c<0時,說明機器人實際上已經移動到表面4的上側,對應的規律就是r變爲0【由於反正題目中只移動一步因此肯定是在表面4的第一行】而c變爲本來的r值。direction也會從原來的left變爲down。 其餘狀況以此類推。
當在與底面毗鄰的表面1/2/3/4試圖往底面移動時(e.g. grid==2, location_r<0)時會失敗,把當前非法的座標值更新爲邊界值,方向不變。
[4] 最後返回當前記錄的grid值
關於grid location和directon的追蹤
實現所有在main裏寫也是沒問題,可是我比較喜歡分紅幾個函數來寫。這樣的話爲了保證函數中作的變動能更新到main裏的表面/座標/方向的變量值就須要把它們按引用傳遞而不是按值傳遞, C/C++能夠把參數設爲引用或者指針,java的話好像基本數據類型參數是默認按值傳遞的,但好像也有個什麼途徑能夠把它們封裝成對象就能按引用傳遞了。
若是大家直接把它們用做返回值當我沒說
用全局變量也能夠啦但我不是很喜歡
整體
int grid = 1, location_r, location_c, direction; void robot_move(int& location_r, int& location_c, int& direction); bool locationInvalid(const int location_r, const int location_c, const int N); void robot_rectify(int& grid, int& location_r, int& location_c, int& direction, const int N); void changeDirection(int& direction, const int op); //依此執行輸入指令 for (int op : ops) { switch (op) { case 1: //move forward robot_move(location_r, location_c, direction); //update location if (locationInvalid(location_r, location_c, N)) robot_rectify(grid, location_r, location_c, direction, N); //rectify the illegal location values and udpate direction perhaps break; case 2: case 3: changeDirection(direction, op); break; } }
完整代碼:
#include <iostream> using namespace std; enum directions { up, left, down, right }; int deltas[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } }; void robot_move(int& location_r, int& location_c, int& direction) { //increment locations with specific delta according to the current direction location_r += deltas[direction][0]; location_c += deltas[direction][1]; } bool locationInvalid(const int location_r, const int location_c, const int N) { return location_r < 0|| location_r >= N || location_c < 0 || location_c >= N; } void robot_rectify(int& grid, int& location_r, int& location_c, int& direction, const int N) { switch (grid) { case 1: if (location_r < 0) { grid = 5; location_r = N - 1; } else if (location_r >= N) { location_r = N - 1; } else if (location_c < 0) { grid = 4; location_c = N - 1; } else if (location_c >= N) { grid = 3; location_c = 0; } break; case 2: if (location_r < 0) { location_r = 0; } else if (location_r >= N) { grid = 5; location_r = 0; } else if (location_c < 0) { grid = 4; direction = directions::right; location_r = N - 1 - location_r; location_c = 0; } else if (location_c >= N) { grid = 3; direction = directions::left; location_r = N - 1 - location_r; location_c = N - 1; } break; case 3: if (location_r < 0) { grid = 5; direction = directions::left; location_r = N-1-location_c; location_c = N - 1; } else if (location_r >= N) { location_r = N - 1; } else if (location_c < 0) { grid = 1; location_c = N - 1; } else if (location_c >= N) { grid = 2; direction = directions::right; location_r = N - 1 - location_r; location_c = N - 1; } break; case 4: if (location_r < 0) { grid = 5; direction = directions::right; location_r = location_c; location_c = 0; } else if (location_r >= N) { location_r = N - 1; } else if (location_c < 0) { grid = 2; direction = directions::right; location_r = N - 1 - location_r; location_c = 0; } else if (location_c >= N) { grid = 1; location_c = 0; } break; case 5: if (location_r < 0) { grid = 2; location_r = N - 1; } else if (location_r >= N) { grid = 1; location_r = 0; } else if (location_c < 0) { grid = 4; direction = directions::down; location_c = location_r; location_r = 0; } else if (location_c >= N) { grid = 3; direction = directions::down; location_c = N-1-location_r; location_r = 0; } break; } } void changeDirection(int& direction, const int op) { switch (op) { case 2://turn right if (direction == directions::up) direction = directions::right; else --direction; break; case 3://turn left if (direction == directions::right) ++direction; else ++direction; break; } } int main() { //input & initialization int N, grid, location_r, location_c, direction, k, ops[200]; cin >> N >> location_r >> location_c >> k; --location_r; --location_c; for (int i = 0; i < k; i++) cin >> ops[i]; /* test case int N = 4, grid, location_r = 2, location_c = 1, direction, k = 25; int ops[200] = { 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 3, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1 }; */ grid = 1; direction = directions::up; //依次執行輸入指令 for (int i = 0; i < k; i++) { switch (ops[i]) { case 1: //move forward robot_move(location_r, location_c, direction); //update location if (locationInvalid(location_r, location_c, N)) robot_rectify(grid, location_r, location_c, direction, N); //rectify the illegal location values and udpate direction perhaps break; case 2: case 3: changeDirection(direction, ops[i]); break; } } cout << grid << endl; return 0; }