八数码之双广解决方法

来源:互联网 发布:c语言的发展历程 编辑:程序博客网 时间:2024/04/29 09:09

从起始状态和末尾状态分别进行bfs,每次从队列节点少的队列进行遍历,当两个队列重合的时候就是找到答案的时候。

#include<iostream>using namespace std;#define SWAP(a, b) {char t = a; a = b; b = t;}const int MAXN = 200000;struct Node{    char tile[10];      //数据    int parent;         //父节点    int pos;            //x的位置    char dir;           //方向};Node qu[2][MAXN];       //两个队列int head[2], tail[2];   //两个队列的头和尾int _move[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };char _dir[4][2] = { { 'u', 'd' }, { 'd', 'u' }, { 'l', 'r' }, { 'r', 'l' } };char _start[10], _end[10] = "12345678x";//初始化void init(int qi, const char* state){    strcpy(qu[qi][0].tile, state);    qu[qi][0].pos = strchr(state, 'x') - state;    qu[qi][0].parent = -1;    head[qi] = tail[qi] = 0;}//输入void input(){    for (int i = 0; i < 9; i++){        cin >> _start[i];    }    _start[9] = '\0';    init(0, _start);    init(1, _end);}//判断是否重复int isVis(int id){    for (int i = 0; i < tail[id]; i++){        if (strcmp(qu[id][i].tile, qu[id][tail[id]].tile) == 0) return 1;    }    return 0;}//判断是否和另一个队列重合int isResult(int id){    for (int i = 0; i < tail[1-id]; i++){        if (strcmp(qu[1-id][i].tile, qu[id][tail[id]].tile) == 0) return i;    }    return -1;}void print_backward(int i){    if (qu[0][i].parent != -1)    {        print_backward(qu[0][i].parent);        printf("%c", qu[0][i].dir);    }}void print_forward(int j){    if (qu[1][j].parent != -1)    {        printf("%c", qu[1][j].dir);        print_forward(qu[1][j].parent);    }}void print_result(int i, int j){    //printf("%d,%d\n", i, j);    print_backward(i);    print_forward(j);    printf("\n");}//广度搜索int bfs(int id){    int r;    Node temp,p = qu[id][head[id]++];    for (int i = 0; i < 4; i++){        int x = p.pos / 3 + _move[i][0];        int y = p.pos % 3 + _move[i][1];        if (x < 0 || x >= 3 || y < 0 || y >= 3) continue;        strcpy(temp.tile, p.tile);        SWAP(temp.tile[p.pos],temp.tile[3*x+y]);        temp.parent = head[id] - 1;        temp.pos = x * 3 + y;        temp.dir = _dir[i][id];        qu[id][++tail[id]] = temp;        if (isVis(id)){                     //判断是否存在            tail[id]--;        }        else                                //判断向队列有重合        {            if ((r=isResult(id))!=-1){                if (id){                    //在判断 逆 队列时                    print_result(r, tail[1]);                }                else                        //在判断 顺 队列时                {                    print_result(tail[0], r);                }                return 1;            }        }    }    return 0;}int solve(){    while (head[0] <= tail[0] && head[1] <= tail[1])    {        if (tail[0] - head[0] >= tail[1] - head[1]){            if (bfs(1)) return 1;        }        else        {            if (bfs(0)) return 1;        }    }    return 0;}int main(){    input();    if (!solve()){    }}
0 0