POJ1077 Eight —— 正向BFS

来源:互联网 发布:淘宝直通车没有展现量 编辑:程序博客网 时间:2024/05/19 06:16

主页面:http://blog.csdn.net/dolfamingo/article/details/77825569



代码一:以数组充当队列,利用结构体中的pre追溯上一个状态在数组(队列)中的下标:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>#include <string>#include <set>#define ms(a,b) memset((a),(b),sizeof((a)))using namespace std;typedef long long LL;const int INF = 2e9;const LL LNF = 9e18;const int MOD = 1e9+7;const int MAXN = 1e6+10;#define AIM  1     //123456789的哈希值为1struct node{    int status;    int s[9];    int loc;    char path;    int pre;  //pre为上一个操作在队列中的下标,用于输出路径};int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 };char op[4] = {'u', 'd', 'l', 'r'  };int cantor(int s[])  //获得哈希函数值{    int sum = 0;    for(int i = 0; i<9; i++)    {        int num = 0;        for(int j = i+1; j<9; j++)            if(s[j]<s[i])                num++;        sum += num*fac[8-i];    }    return sum+1;}node que[MAXN];int front, rear;int bfs(node now){    ms(vis,0);    front = rear = 0;    now.status = cantor(now.s);    vis[now.status] = 1;    que[rear++] = now;    node tmp;    while(front!=rear)    {        now = que[front++];        if(now.status==AIM)            return front-1;        int x = now.loc/3;        int y = now.loc%3;        for(int i = 0; i<4; i++)        {            int xx = x + dir[i][0];            int yy = y + dir[i][1];            if(xx>=0 && xx<=2 && yy>=0 && yy<=2)            {                tmp = now;                tmp.s[x*3+y] = tmp.s[xx*3+yy];  //交换位置,下同                tmp.s[xx*3+yy] = 9;                tmp.status = cantor(tmp.s);                if(!vis[tmp.status])                {                    vis[tmp.status] = 1;                    tmp.loc = xx*3+yy;                    tmp.path = op[i];     //保存操作                    tmp.pre = front-1;  //保存当前结点的状态的上一个状态所在的结点在数组(队列)的下标                    que[rear++] = tmp;                }            }        }    }    return -1;}void Print(int i)   //利用递归的特点(压栈),输出路径{    if(i==0) return;    //到了目的状态,则退出。目的状态的结点在数组(队列)中的下标为0    Print(que[i].pre);  //访问上一步    putchar(que[i].path); //输出操作}int main(){    char tmp[50];    while(gets(tmp))    {        node beg;        int cnt = 0;        for(int i = 0; tmp[i]; i++)        {            if(tmp[i]==' ') continue;            if(tmp[i]=='x') beg.s[cnt] = 9, beg.loc = cnt++;            else  beg.s[cnt++] = tmp[i]-'0';        }        int i = bfs(beg);        if(i==-1)            puts("unsolvable");        else            Print(i), putchar('\n');    }}


代码二(推荐):把pre和path放在结构体外,利用当前状态status追溯上一个状态status:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>#include <string>#include <set>#define ms(a,b) memset((a),(b),sizeof((a)))using namespace std;typedef long long LL;const int INF = 2e9;const LL LNF = 9e18;const int MOD = 1e9+7;const int MAXN = 1e6+10;#define AIM  1     //123456789的哈希值为1struct node{    int status;    int s[9];    int loc;};int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 };char op[4] = {'u', 'd', 'l', 'r'  };char path[MAXN];int pre[MAXN];int cantor(int s[])  //获得哈希函数值{    int sum = 0;    for(int i = 0; i<9; i++)    {        int num = 0;        for(int j = i+1; j<9; j++)            if(s[j]<s[i])                num++;        sum += num*fac[8-i];    }    return sum+1;}queue<node>que;bool bfs(node now){    ms(vis,0);    while(!que.empty()) que.pop();    now.status = cantor(now.s);    pre[now.status] = -1;   //开始状态的上一个状态为-1,用于输出路径时“刹车”    vis[now.status] = 1;    que.push(now);    node tmp;    while(!que.empty())    {        now = que.front();        que.pop();        if(now.status==AIM) //找到了123456789的状态            return true;        int x = now.loc/3;        int y = now.loc%3;        for(int i = 0; i<4; i++)        {            int xx = x + dir[i][0];            int yy = y + dir[i][1];            if(xx>=0 && xx<=2 && yy>=0 && yy<=2)            {                tmp = now;                tmp.s[x*3+y] = tmp.s[xx*3+yy];  //交换位置,下同                tmp.s[xx*3+yy] = 9;                tmp.status = cantor(tmp.s);                if(!vis[tmp.status])                {                    vis[tmp.status] = 1;                    tmp.loc = xx*3+yy;                    pre[tmp.status] = now.status;   //tmp.status的上一个状态为now.status                    path[tmp.status] = op[i];   //保存操作                    que.push(tmp);                }            }        }    }    return 0;}void Print(int status){    if(pre[status]==-1) return;    Print(pre[status]);     //追溯上一个状态    putchar(path[status]);}int main(){    char str[50];    while(gets(str))    {        node now;        int cnt = 0;        for(int i = 0; str[i]; i++)        {            if(str[i]==' ') continue;            if(str[i]=='x') now.s[cnt] = 9, now.loc = cnt++;            else  now.s[cnt++] = str[i]-'0';        }        if(!bfs(now))            puts("unsolvable");        else            Print(AIM), putchar('\n');    }}


原创粉丝点击