典型的广搜题目:
1) 首先把初始状态所代表的节点压入队列,初始节点的状态为12348765,父节点位置为-1(表示没有父节点),op为空,表示没有操作,标记初始节点的状态已访问,初始化step(表示当前搜索的层次)为0;
2) 当队列不为空(head< tail),一直循环以下步骤;
3) 用一个curTail记录当前队列的队尾,这表示了从head到curTail为层次为step的这一层,对这一层的节点进行扩展。
4) 对于当前这一层的所有节点,首先判断它的状态是否为目标状态,如果是表示找到了结果,标记成功并且输出路径,退出。如果不是目标状态,则分别按照A、B、C三个操作来扩展,如果扩展之后的节点状态是以前没有达到过的,那么就压入队列(tail++),并且标记该状态已访问(对于每一个状态可以通过康托展开来做hash,使得一个节点映射为一个更小的整数)。
5) 当前整一层访问完毕,step++,如果step大于了输入的N,则退出,表示没有完成任务。
6) 如果step不大于输入的N,表示搜索没有结束,转到第2)步继续进行。
#include <cstdio> #include <cstring> int fact[] = {1, 1, 2, 6, 24, 120, 720, 5040}; bool vis[40500]; struct Node { int state, p; char op; }que[40500]; int op(int state, int c)//三步操作 { int res = 0; switch(c) { case 1: res = state/10000 + state%10000*10000; break; case 2: res = state/10000%10*10000000 + state/100000*10000 +state%10*1000 + state/10%1000; break; case 3: res = state/10000000*10000000 + state/100%10*1000000 + state/1000000%10*100000 + state/10000%10*10000 + state/1000%10*1000 + state/10%10*100 + state/100000%10*10 + state%10; break; } return res; } int hash(int state)//康托展开 { char str[10]; int res = 0; sprintf(str, "%d", state); for(int i=0; i<8; i++) { int cnt = 0; for(int j=i+1; j<8; j++) if(str[i] > str[j]) cnt++; res += cnt*fact[7-i]; } return res; } void print(int p)//打印路径 { if(p != -1) { print(que[p].p); printf("%c", que[p].op); } } int main() { int M, startState = 12348765; while(scanf("%d", &M), M != -1) { int endState = 0, val, step = 0, head = 0, tail = 1; bool hasfinished = false; for(int i=0; i<8; i++) { scanf("%d", &val); endState = endState*10 + val; } memset(vis, false, sizeof(vis)); que[0].state = startState, que[0].p = -1; vis[hash(startState)] = true; while(head < tail && !hasfinished)//队列不为空,或者搜索还未结束,继续 { int curTail = tail;//curTail为测试为step的这一层的最后一个节点的位置 while(head < curTail) { int curState = que[head++].state; if(curState == endState) { printf("%d ", step); print(head-1); printf("\n"); hasfinished = true; break; } for(int i=1; i<=3; i++) { int tmp = op(curState, i); int tmpHash = hash(tmp); if(!vis[tmpHash]) { vis[tmpHash] = true; que[tail].state = tmp, que[tail].p = head - 1, que[tail++].op = (char)(i- 1+'A'); } } } step++;//搜索层次加一 if(step > M) break; } if(!hasfinished) printf("-1\n"); } return 0; }