ZOJ - 3467 3D Knight Moves

 

一、题目略
二、解题思路简介(参考http://watashi.ws/blog/1877/zojmonthly1102/):
由于一次移动可以有48个选择,如果移动6次的话48^6就......
所以正向bfs三层,反向bfs3层。
麻烦的是要记录路径而且还要是字典序的 -_- 。
参考代码中是用map对每一个点保存一条路径,我完全模仿了....
三、代码
下面的代码几乎就是参考代码:
不过是我边想,边慢慢打出来的哦。

对STL的掌握又增加了那么一点点。

 

#include <cstdio> #include <vector> #include <map> #include <algorithm> using namespace std; struct Point { //3D中的一个点 int x, y, z; Point() {} Point(int x, int y, int z) : x(x), y(y), z(z) {} }; //使vector能直接通过符号比较 bool operator < (const Point& a, const Point& b) { if(a.x != b.x) { return a.x < b.x; } else if(a.y != b.y) { return a.y < b.y; } else { return a.z < b.z; } } //两个点的相加 Point operator + (const Point& a, const Point& b) { return Point(a.x + b.x, a.y + b.y, a.z + b.z); } typedef map<Point, vector<Point> > Hash; Hash bfs[4], rbfs[4]; vector<Point> dir; //计算各个方向的坐标 void calDir(int x, int y, int z) { int d[3] = {x, y, z}; dir.clear(); sort(d, d+3); do { for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { for(int z = 0; z < 2; z++) { dir.push_back(Point(d[0], d[1], d[2])); d[2] = -d[2]; } d[1] = -d[1]; } d[0] = -d[0]; } }while(next_permutation(d, d + 3)); } //扩展一层 void work(Hash& from, Hash& to) { for(Hash::const_iterator it = from.begin(); it != from.end(); it++) { for(vector<Point>::const_iterator j = dir.begin(); j != dir.end(); j++) { vector<Point>& k = to[it->first + *j]; if(k.empty() || k > it->second) { k = it->second; } } } } int main(int argc, char* argv[]) { int x0, y0, z0, x1, y1, z1, x, y, z; vector<Point> ans, tmp; Hash::const_iterator ptr; bool flag; while(scanf("%d%d%d%d%d%d%d%d%d", &x0, &y0, &z0, &x1, &y1, &z1, &x, &y, &z) != EOF) { calDir(x, y, z); for(int i = 0; i < 3; i++) { bfs[i].clear(); rbfs[i].clear(); } ans.clear(); bfs[0][Point(x0, y0, z0)]; rbfs[0][Point(x1, y1, z1)]; flag = false; // 移动距离为0的情况 if (bfs[0].find(rbfs[0].begin()->first) != bfs[0].end()) { flag = true; } //正向3层 for(int i = 1; i <= 3 && !flag; i++) { work(bfs[i-1], bfs[i]); for(Hash::iterator it = bfs[i].begin(); it != bfs[i].end(); it++) { it->second.push_back(it->first); } if((ptr = bfs[i].find(rbfs[0].begin()->first)) != bfs[i].end()) { ans = ptr->second; flag = true; } } //反向3层 for(int i = 1; i <= 3 && !flag; i++) { for(Hash::iterator it = rbfs[i-1].begin(); it != rbfs[i-1].end(); it++) { it->second.insert(it->second.begin() ,it->first); } work(rbfs[i-1], rbfs[i]); for(Hash::const_iterator j = rbfs[i].begin(); j != rbfs[i].end(); j++) { if((ptr = bfs[3].find(j->first)) != bfs[3].end()) { tmp = ptr->second; tmp.insert(tmp.end(), j->second.begin(), j->second.end()); ans = ans.empty() ? tmp : min(ans, tmp); flag = true; } } } printf("To get from (%d,%d,%d) to (%d,%d,%d) takes ", x0, y0, z0, x1, y1, z1); if(flag) { printf("%d 3D knight moves (%d,%d,%d): (%d,%d,%d)", ans.size(), x, y, z, x0, y0, z0); for(vector<Point>::const_iterator it = ans.begin(); it != ans.end(); it++) { printf(" => (%d,%d,%d)", it->x, it->y, it->z); } } else { printf("more than 6 3D knight moves (%d,%d,%d)", x, y, z); } puts("."); } return 0; } 

 

体会:

①感觉好麻烦,都差点写糊涂了...

②STL的确很强大,能提供比C强大得多的抽象机制。感觉更适合竞赛。 

你可能感兴趣的:(ZOJ - 3467 3D Knight Moves)