ZOJ - 3467   3D Knight Moves

一、题目略

二、解题思路简介(参考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强大得多的抽象机制。感觉更适合竞赛。 

你可能感兴趣的:(职场,STL,bfs,休闲)