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