难度:β
建议用时:40 min
关于这道题目的背景在维基百科上有。很神奇。
但是我们的这道题没有那么多考虑。上来直接东南西北狂搜一通就好了。
算法很简单,直接上过程。
首先确定 “东”“南”“西”“北” 对应的英文字母 “e”“s”“w”“n”。
因为题目还说不能后退,所以要把后退的方向也处理出来。”东“对”西“ 等等。
因为出发点在(0,0),又可以往负的方向走,为了用数组存,我们给每个坐标加一个 buf = 105 的东西,保证坐标都非负。
1 blocks[x+buf][y+buf] = 1;
另外因为对一个方向最多只走 buf 个距离,因此在范围外的障碍物就 pass 掉。
1 if(abs(x) > buf || abs(y) > buf) continue;
下面直接东南西北搜。
1 void dfs(int curDepth, int curX, int curY, int lastDir) { 2 if(curDepth == lastLenth) { 3 if(curX == startX && curY == startY) { 4 output(); 5 total++; 6 } 7 return; 8 } 9 10 if(is_time_to_go_back(curDepth, curX, curY)) return; 11 12 for(int dir = 0; dir <= 3; dir++) { 13 int newX = curX + dx[dir]*(curDepth+1); 14 int newY = curY + dy[dir]*(curDepth+1); 15 16 if(abs(newX) > buf || abs(newY) > buf) continue; 17 if(block_in_the_way(curX, curY, newX, newY)) continue; 18 if(dir + lastDir == 3 || dir == lastDir) continue; 19 if(vis[newX+buf][newY+buf]) continue; 20 21 vis[newX+buf][newY+buf] = 1; 22 path[curDepth] = dir; 23 dfs(curDepth+1, newX, newY, dir); 24 vis[newX+buf][newY+buf] = 0; 25 } 26 }
注意这里的细节:
1 if(dir + lastDir == 3 || dir == lastDir) continue;
回头看:
1 const char directions[] = {‘e‘, ‘n‘, ‘s‘, ‘w‘};
哦!好妙!判断方向方便很多!小技巧。
作为一到剪枝题,这里的重点就在剪枝函数 “is_time_to_go_back” 上。
先分析一下。要想在规定的步数走回原点,容易想到要限制不能走太远。因为走的距离和是有限的。而这里的距离是以曼哈顿距离为参考的。所以自然要在这方面剪枝。
1 bool is_time_to_go_back(int curDepth, int curX, int curY) { 2 int manhattan_dist = abs(curX) + abs(curY); 3 int remain_dist = S[lastLenth] - S[curDepth]; 4 if(remain_dist < manhattan_dist) return true; 5 return false; 6 }
这个 “S” 就是等差数列前 n 项和。计算出还可以走多少曼哈顿距离。
构造 “S” :
1 void init() { 2 S[0] = 0; 3 for(int i = 1; i <= 20; i++) S[i] = S[i-1] + i; 4 }
这题还需判断有没有障碍物,上 code :
bool block_in_the_way(int sx, int sy, int tx, int ty) { if(sx > tx) swap(sx, tx); if(sy > ty) swap(sy, ty); for(int x = sx; x <= tx; x++) { for(int y = sy; y <= ty; y++) { if(blocks[x+buf][y+buf]) return true; } } return false; }
大概想法就是枚举路上的每一个点,判断是不是障碍物。
注意要保证 x 和 y 的递增。否则枚举会出问题。
总体过程结束了。
这题回头看没有什么难点,曼哈顿距离就是求绝对值之和。不知道还有没有更高效的剪枝方法。
不明白的请留言。
如果你对这篇文章感兴趣,请关注我,我会定期(每天)更新文章。希望一起交流哈~
2018-01-22 00:02:04 (好晚啊)