在发现8!=40320之后,我发现空间不是影响因素了。只要不重复运算,时间和空间都是足够的。
值得借鉴的地方:
1.对于转换的处理:
/* the set of transformations, in order */
static int tforms[3][8] = { {8, 7, 6, 5, 4, 3, 2, 1}, {4, 1, 2, 3, 6, 7, 8, 5},
{1, 7, 2, 4, 5, 3, 6, 8} };
这里是另外一种思路,处理起来相对更简单些。思路是直接将转化理解为对不同拷贝位置(初始位置转换后的位置)的映射。比如第一个转化里面第0为应该拷贝第7位(8-1)。第一个转化其实就是这一个数组,即拷贝位置的映射。
2.康拓展开
康拓展开是个好定理:作用是求一个排列如45213在这个5个数的全排列中的序列。可以直接移步这里:http://blog.csdn.net/fairyroad/article/details/7555773
代码写得很好。
/* ID: thestor1 LANG: C++ TASK: msquare */ #include <iostream> #include <cmath> #include <cstdio> #include <cstring> #include <vector> #include <cassert> #include <string> #include <algorithm> #include <stack> #include <set> using namespace std; const int size = 8; const int MAX = 40320; //8! = 40320 struct Square{ int h; int square[size]; char op; int prev; Square() { h = -1; } int hash() { if(h > 0) { return h; } int h = 0; for(int i = 0; i < size; ++i) { h = (h << 3) + square[i]; } return h; } }; Square squares[MAX]; bool equal(Square &s1, Square &s2) { return s1.hash() == s2.hash(); } bool equal(int *s1, int *s2) { for(int i = 0; i < size; ++i) { if(s1[i] != s2[i]) { return false; } } return true; } void copy(int *s, int *d) { for(int i = 0; i < size; ++i) { d[i] = s[i]; } } void A(int *square) { for(int i = 0; i <= 3; ++i) { int tmp = square[i]; square[i] = square[7 - i]; square[7 - i] = tmp; } } void B(int *square) { int tmp = square[3]; for(int i = 3; i >= 1; --i) { square[i] = square[i - 1]; } square[0] = tmp; tmp = square[4]; for(int i = 4; i <= 6; ++i) { square[i] = square[i + 1]; } square[7] = tmp; } void C(int *square) { int tmp = square[1]; square[1] = square[6]; square[6] = square[5]; square[5] = square[2]; square[2] = tmp; } int main() { FILE *fin = fopen ("msquare.in", "r"); FILE *fout = fopen ("msquare.out", "w"); //freopen("log.txt", "w", stdout); Square targetSq; //int target[size]; for(int i = 0; i < size; ++i) { fscanf(fin, "%d", &targetSq.square[i]); } set<int> sqs; int top = 0; for(int i = 0; i < size; ++i) { squares[top].square[i] = i + 1; } sqs.insert(squares[top].hash()); top++; int final = -1; for(int i = 0; i < top; ++i) { //fprintf(stdout, "i: %d, top: %d\n", i, top); Square sq = squares[i]; if(equal(sq, targetSq)) { final = i; break; } copy(sq.square, squares[top].square); A(squares[top].square); if(sqs.find(squares[top].hash()) == sqs.end()) { squares[top].prev = i; squares[top].op = 'A'; sqs.insert(squares[top].hash()); top++; } copy(sq.square, squares[top].square); B(squares[top].square); if(sqs.find(squares[top].hash()) == sqs.end()) { squares[top].prev = i; squares[top].op = 'B'; sqs.insert(squares[top].hash()); top++; } copy(sq.square, squares[top].square); C(squares[top].square); if(sqs.find(squares[top].hash()) == sqs.end()) { squares[top].prev = i; squares[top].op = 'C'; sqs.insert(squares[top].hash()); top++; } } stack<char> seq; while(final != 0) { seq.push(squares[final].op); final = squares[final].prev; } fprintf(fout, "%d\n", seq.size()); while(!seq.empty()) { fprintf(fout, "%c", seq.top()); seq.pop(); } fprintf(fout, "\n"); return 0; }