楼主: 不zhiwei何
跳转到指定楼层
上一主题 下一主题
收起左侧

谷歌电面跪经

 
🔗
fenghao 2017-8-18 09:38:39 | 只看该作者
全局:
这个题是机器人扫描,不能BFS吧,就是DFS+backtracing
回复

使用道具 举报

🔗
endofunctor 2017-8-20 11:50:36 | 只看该作者
全局:
测了下貌似没问题。。。后面那四个helper应该还可以优化一下,懒得优化了。。。欢迎指正
假设机器人开始向上:
  1. #include <iostream>
  2. #include <vector>
  3. #include <unordered_map>
  4. #include <unordered_set>
  5. using namespace std;

  6. class Robot {
  7. public:
  8.   Robot(vector<string>& grid, int i, int j) : grid(grid), i(i), j(j) {
  9.    
  10.   }
  11.   bool Move() {
  12.     if (i + di < 0 || i + di >= grid.size() || j + dj < 0 || j + dj >= grid[i].size() || grid[i + di][j + dj] == '+')
  13.       return false;
  14.     i += di;
  15.     j += dj;
  16.     return true;
  17.   }

  18.   // Robot will stay on the same cell after calling Turn*. k indicates how
  19.   // many turns to perform.
  20.   int ddi[4] = {0, 1, 0, -1};
  21.   int ddj[4] = {1, 0, -1, 0};
  22.   void TurnRight(int k) {
  23.     int ii = 0;
  24.     for (; ii < 4; ++ii) {
  25.       if (ddi[ii] == di && ddj[ii] == dj)
  26.         break;
  27.     }
  28.     int iii = (ii + k) % 4;
  29.     di = ddi[iii];
  30.     dj = ddj[iii];
  31.   }
  32.   void TurnLeft(int k) {
  33.     int ii = 0;
  34.     for(; ii < 4; ++ii) {
  35.       if (ddi[ii] == di && ddj[ii] == dj)
  36.         break;
  37.     }
  38.     int iii = (ii - k) % 4;
  39.     di = ddi[iii];
  40.     dj = ddj[iii];
  41.   }
  42.   // Clean the current cell.
  43.   void Clean() {
  44.     grid[i][j] = ' ';
  45.   }
  46. private:
  47.   vector<string>& grid;
  48.   int i;
  49.   int j;
  50.   int di = 1;
  51.   int dj = 0;
  52. };
  53. // after each move, recover the direction of robots
  54. bool moveLeft(Robot& r) {
  55.   r.TurnRight(3);
  56.   bool possible = r.Move();
  57.   r.TurnRight(1);
  58.   return possible;
  59. }

  60. bool moveRight(Robot& r) {
  61.   r.TurnRight(1);
  62.   bool possible = r.Move();
  63.   r.TurnRight(3);
  64.   return possible;
  65. }

  66. bool moveUp(Robot& r) {
  67.   bool possible = r.Move();
  68.   return possible;
  69. }

  70. bool moveDown(Robot& r) {
  71.   r.TurnRight(2);
  72.   bool possible = r.Move();
  73.   r.TurnRight(2);
  74.   return possible;
  75. }

  76. void helper1(Robot& r, unordered_map<int, unordered_set<int> >& visited, int i, int j) {
  77.   // left, up, down
  78.   if (visited.count(i) && visited[i].count(j))
  79.     return;
  80.   r.Clean();
  81.   //r.print();
  82.   visited[i].insert(j);
  83.   if (moveLeft(r)) {
  84.     helper1(r, visited, i, j - 1);
  85.     moveRight(r);
  86.   }
  87.   if (moveUp(r)) {
  88.     helper1(r, visited, i + 1, j);
  89.     moveDown(r);
  90.   }
  91.   if (moveDown(r)) {
  92.     helper1(r, visited, i - 1, j);
  93.     moveUp(r);
  94.   }
  95.   return;
  96. }

  97. void helper2(Robot& r, unordered_map<int, unordered_set<int> >& visited, int i, int j) {
  98.   // up left right
  99.   if (visited.count(i) && visited[i].count(j))
  100.     return;
  101.   r.Clean();
  102.   visited[i].insert(j);
  103.   if (moveUp(r)) {
  104.     helper2(r, visited, i + 1, j);
  105.     moveDown(r);
  106.   }
  107.   if (moveLeft(r)) {
  108.     helper2(r, visited, i, j - 1);
  109.     moveRight(r);
  110.   }
  111.   if (moveRight(r)) {
  112.     helper2(r, visited, i, j + 1);
  113.     moveLeft(r);
  114.   }
  115.   return;
  116. }

  117. void helper3(Robot& r, unordered_map<int, unordered_set<int> >& visited, int i, int j) {
  118.   // up right down
  119.   if (visited.count(i) && visited[i].count(j))
  120.     return;
  121.   r.Clean();
  122.   visited[i].insert(j);
  123.   if (moveUp(r)) {
  124.     helper3(r, visited, i + 1, j);
  125.     moveDown(r);
  126.   }
  127.   if (moveRight(r)) {
  128.     helper3(r, visited, i, j + 1);
  129.     moveLeft(r);
  130.   }
  131.   if (moveDown(r)) {
  132.     helper3(r, visited, i - 1, j);
  133.     moveUp(r);
  134.   }
  135.   return;
  136. }

  137. void helper4(Robot& r, unordered_map<int, unordered_set<int> >& visited, int i, int j) {
  138.   // left down right                                                                                                                        
  139.   if (visited.count(i) && visited[i].count(j))
  140.     return;
  141.   r.Clean();
  142.   visited[i].insert(j);
  143.   if (moveLeft(r)) {
  144.     helper4(r, visited, i, j - 1);
  145.     moveRight(r);
  146.   }
  147.   if (moveDown(r)) {
  148.     helper4(r, visited, i - 1, j);
  149.     moveUp(r);
  150.   }
  151.   if (moveRight(r)) {
  152.     helper4(r, visited, i, j + 1);
  153.     moveLeft(r);
  154.   }
  155.   return;
  156. }

  157. void cleanAll(Robot& r) {
  158.   unordered_map<int, unordered_set<int> > visited;
  159.   helper1(r, visited, 0, 0);
  160.   visited.clear();
  161.   helper2(r, visited, 0, 0);
  162.   visited.clear();
  163.   helper3(r, visited, 0, 0);
  164.   visited.clear();
  165.   helper4(r, visited, 0, 0);
  166. }

  167. int main() {
  168.   vector<string> layout({
  169.       "++++++++++",
  170.         "+........+",
  171.         "+........+",
  172.         "+.+......+",
  173.         "++++.+++++",
  174.         "+.....+",
  175.         "+++++++"
  176.         });
  177.   Robot r(layout, 2, 4);
  178.   cleanAll(r);
  179.   for (auto s: layout)
  180.     cout << s << endl;
  181.   return 0;
  182. }
复制代码
回复

使用道具 举报

🔗
 楼主| 不zhiwei何 2017-8-21 11:58:24 | 只看该作者
全局:
endofunctor 发表于 2017-8-19 19:50
测了下貌似没问题。。。后面那四个helper应该还可以优化一下,懒得优化了。。。欢迎指正
假设机器人开始向 ...

层主辛苦了,,,但是当时面试时的题目是,要用他给的inteface Robot里面的methods,并不需要自己实现这些methods。。。
回复

使用道具 举报

🔗
endofunctor 2017-8-21 12:05:42 | 只看该作者
全局:
不zhiwei何 发表于 2017-8-21 11:58
层主辛苦了,,,但是当时面试时的题目是,要用他给的inteface Robot里面的methods,并不需要自己实现这 ...

多谢多谢。。。因为没啥办法模拟所以只好自己写一个了。。。82行开始才是干货
回复

使用道具 举报

🔗
fenghao 2017-8-21 15:02:43 | 只看该作者
全局:
reliveinfire 发表于 2017-8-16 14:04
我的想法是dfs traversal, 当从dfs离开, 要回到之前的点, 并且将robot的方向, 找到call dfs时的方向, 不知 ...

我觉得基本就是这个解法,主要就是注意是机器人,保证方向在进入深层递归中不变,同时从深层递归返回时调整方向
回复

使用道具 举报

🔗
baudelaire 2017-8-21 20:34:31 | 只看该作者
全局:
感觉是dfs+backtrack 不过房子太大了可能会爆栈。 写了一下代码 请大神们指教!
  1.    
  2.     int[][] dirs = new int[][]{{0,1}, {1,0}, {0,-1}, {-1,0}};
  3.     Set<String> memo = new HashSet<>();
  4.     public void dfsClean(int x, int y, int d, Set<String> memo){
  5.         // x,y: position, d: direction
  6.         String hcode = x+":"+y;
  7.         this.Clean();
  8.         memo.add(hcode);
  9.         for(int i=0; i<4; i++){
  10.             this.TurnRight(i>0?1:0); // first go ahead, then each time one turn
  11.             int nd = (d+i)%4;
  12.             int nx = x+dirs[nd][0];
  13.             int ny = y+dirs[nd][1];
  14.             String ncode = nx+":"+ny;
  15.             if(!memo.contains(ncode)){
  16.                 if(this.Move()){
  17.                     dfsClean(nx, ny, nd, memo);// take care to orient to oposite direction of nd
  18.                     // move back and turn to nd
  19.                     this.Move();
  20.                     // reset to direction before
  21.                     this.TurnRight(2);
  22.                 }else{
  23.                     // obstacle found, remember it
  24.                     memo.add(ncode);
  25.                 }
  26.             }
  27.         }
  28.         // orient robot to oposite direction of d
  29.         this.TurnRight(2);
  30.     }
复制代码

补充内容 (2017-8-21 20:37):
最后两行应该为
        // orient robot to oposite direction of d
        this.TurnRight(3);

补充内容 (2017-8-21 20:39):
感觉这题不应该使用input里边那些字符,因为扫地机器人是盲扫,根本不知道房子的地图,面试官给个input估计是为了便于理解

评分

参与人数 3大米 +30 收起 理由
iamone14 + 10 很有用的信息!
xh_pku + 10 给你点个赞!
chouclee + 10 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
baudelaire 2017-8-21 20:48:41 | 只看该作者
全局:
reliveinfire 发表于 2017-8-16 14:04
我的想法是dfs traversal, 当从dfs离开, 要回到之前的点, 并且将robot的方向, 找到call dfs时的方向, 不知 ...

感觉只用一个hash set存相对坐标就行了, 机器人不管起始放在哪都设成(0,0)。 另外大神你这个代码会让机器人随后停止的位置和起始位置不一样,因为你最后backtrack的时候把机器人往下移了一格
回复

使用道具 举报

无效楼层,该帖已经被删除
🔗
codemonk 2017-8-25 00:22:29 | 只看该作者
全局:
看上去有点类似口袋宝石的一道面经 机器人格子
http://www.1point3acres.com/bbs/thread-287234-1-1.html

  1. #include <iostream>
  2. #include <vector>
  3. #include <stack>
  4. #include <unordered_set>
  5. #include <unordered_map>
  6. using namespace std;

  7. // r, c are coordinates, turn : track how many turns made in the current position
  8. struct int3{
  9.     int r, c, turn;
  10. };

  11. class Robot {
  12. public:
  13.     // returns true if next cell is open and robot moves into the cell.
  14.     // returns false if next cell is obstacle and robot stays on the current cell.
  15.     int m, n, r, c;
  16.     vector<vector<char>> maze;
  17.     stack<int3> sk;
  18.     unordered_set<int> visited;
  19.     int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};
  20.     int robotDir;
  21.    
  22.     // assume robot facing upward initially
  23.     Robot(vector<vector<char>>& maze, int r, int c) {
  24.         this->maze = maze;
  25.         this->r = r;
  26.         this->c = c;
  27.         m = maze.size(), n = maze[0].size();
  28.         sk.push({r, c, 0}); // to guard against stack overflow, I write the function call stack explicitly by myself  instead of doing recursion.
  29.         visited.insert(r*n + c);
  30.         robotDir = 0; // track robot last facing direction before hit this grid point
  31.         // robotDir : 0 up, 1 right, 2 down, 3 left
  32.     }
  33.    
  34.     bool Move(){
  35.         r = sk.top().r, c = sk.top().c;
  36.         int& countTurn = sk.top().turn;
  37.         
  38.         if(countTurn == 0) {
  39.             Clean(); // in a new position, clean it
  40.             robotDir--; // make robot start search the current facing direction first
  41.         }
  42.         
  43.         if(countTurn < 4) { // search neighbors
  44.             TurnRight(1); // adjust robot facing position
  45.             countTurn++;
  46.             
  47.             int rr = r + dr[robotDir], cc = c + dc[robotDir];
  48.             if(rr >= 0 && rr < m && cc >= 0 && cc < n && maze[rr][cc] != '+' && !visited.count(rr*n + cc)) {
  49.                 visited.insert(rr*n + cc);
  50.                 sk.push({rr, cc, 0});
  51.                 return true; // explore a new neighbor
  52.             }
  53.             else return false; // obstacle, stay there
  54.         }
  55.         else { // if all neighbors have been searched, go back
  56.             // reset to initial direction before entering this position
  57.             TurnRight(1); // adjust robot facing position
  58.             
  59.             // go back()
  60.             sk.pop();
  61.             return false;
  62.         }
  63.     }
  64.    
  65.     // Robot will stay on the same cell after calling Turn*. k indicates how
  66.     // many turns to perform.
  67.     void TurnLeft(int k) {}
  68.     void TurnRight(int k) {robotDir = (robotDir + 1) % 4;}
  69.    
  70.     // Clean the current cell.
  71.     void Clean() {
  72.         maze[r][c] = 'O';
  73.     }
  74.    
  75.     void printBoard() {
  76.         cout << endl;
  77.         for(auto row : maze) {
  78.             for(char c : row) {
  79.                 cout << c;
  80.             }
  81.             cout << endl;
  82.         }
  83.     }
  84. };


  85. int main(int argc, const char * argv[]) {
  86.     // insert code here...
  87.     vector<string> input = {
  88.         "++++++++++",
  89.         "+........+",
  90.         "+...^....+",
  91.         "+.+......+",
  92.         "++++.+++++",
  93.         "+.....+",
  94.         "+++++++"
  95.     };
  96.     vector<vector<char>> maze;
  97.     for(string s : input){
  98.         maze.push_back(vector<char>({}));
  99.         for(char c : s) {
  100.             maze.back().push_back(c);
  101.         }
  102.     }
  103.     Robot rob(maze, 2, 2);
  104.     while(!rob.sk.empty()) {
  105.         rob.Move();
  106.         rob.printBoard();
  107.     }
  108.     return 0;
  109. }
复制代码


回复

使用道具 举报

🔗
Urumic 2017-11-15 03:05:04 | 只看该作者
全局:
这个应该用DFS吧,因为更贴切机器人一次只走一条路的行为吧。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表