典型的广搜题目:
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;
}