POJ1077 Eight —— 双向BFS

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

(代码一直在精简完善……)



代码一:两个BFS, 两段代码; 用step控制“你一步, 我一步”。

#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;

struct node
{
    int status;
    int s[9];
    int loc;
    int step;   //双向bfs需要记录第几步,才能做到“你一步,我一步”
};

int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir1[4][2] = { -1,0, 1,0, 0,-1, 0,1 };  //正方向
char op1[4] = {'u', 'd', 'l', 'r'  };
int dir2[4][2] = {0,1, 0,-1, 1,0, -1,0};    //反方向
char op2[4] = {'l', 'r', 'u', 'd'  };

char path1[MAXN], path2[MAXN];  //1为正方向,2为反方向,以下皆如此
int pre1[MAXN], pre2[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>q1, q2;
int vis1[MAXN], vis2[MAXN];
int bfs(node now)
{
    ms(vis1,0);
    ms(vis2,0);
    while(!q1.empty()) q1.pop();
    while(!q2.empty()) q2.pop();

    now.status = cantor(now.s);
    now.step = 0;
    pre1[now.status] = -1;
    vis1[now.status] = 1;
    q1.push(now);

    for(int i = 0; i<9; i++)
        now.s[i] = i+1;
    now.loc = 8;
    now.status = cantor(now.s);
    now.step = 0;
    pre2[now.status] = -1;
    vis2[now.status] = 1;
    q2.push(now);

    int time = 0;   //计时器
    while(!q1.empty() || !q2.empty())
    {
        time++;
        while(!q1.empty())
        {
            if(q1.front().step==time)   //时间到了,就让给对方
                break;

            now = q1.front();
            q1.pop();

            if(vis2[now.status])    //此状态已被对方访问过,则说明两者“接上了”
                return now.status;

            int x = now.loc/3;
            int y = now.loc%3;
            for(int i = 0; i<4; i++)
            {
                int xx = x + dir1[i][0];
                int yy = y + dir1[i][1];
                if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
                {
                    node tmp = now;
                    tmp.s[x*3+y] = tmp.s[xx*3+yy];
                    tmp.s[xx*3+yy] = 9;
                    tmp.status = cantor(tmp.s);
                    if(!vis1[tmp.status])
                    {
                        vis1[tmp.status] = 1;
                        tmp.loc = xx*3+yy;
                        tmp.step++;
                        path1[tmp.status] = op1[i];
                        pre1[tmp.status] = now.status;
                        q1.push(tmp);
                    }
                }
            }
        }

        while(!q2.empty())
        {
            if(q2.front().step==time)   //时间到了,就让给对方
                break;

            now = q2.front();
            q2.pop();

            if(vis1[now.status])    //此状态已被对方访问过,则说明两者“接上了”
                return now.status;

            int x = now.loc/3;
            int y = now.loc%3;
            for(int i = 0; i<4; i++)
            {
                int xx = x + dir2[i][0];
                int yy = y + dir2[i][1];
                if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
                {
                    node tmp = now;
                    tmp.s[x*3+y] = tmp.s[xx*3+yy];
                    tmp.s[xx*3+yy] = 9;
                    tmp.status = cantor(tmp.s);
                    if(!vis2[tmp.status])
                    {
                        vis2[tmp.status] = 1;
                        tmp.loc = xx*3+yy;
                        tmp.step++;
                        path2[tmp.status] = op2[i];
                        pre2[tmp.status] = now.status;
                        q2.push(tmp);
                    }
                }
            }
        }
    }
    return -1;
}


void Print1(int status) //输出正方向的路径
{
    if(pre1[status]==-1) return;
    Print1(pre1[status]);
    putchar(path1[status]);
}

void Print2(int status) //输出反方向的路径
{
    if(pre2[status]==-1) return;
    putchar(path2[status]);
    Print2(pre2[status]);
}

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 status = bfs(beg);
        if(status==-1)
            puts("unsolvable");
        else
        {
            Print1(status); Print2(status);   //输出路径
            putchar('\n');
        }
    }
}



代码二:两个BFS, 两段代码; 用队列的大小控制“你一步, 我一步”。

#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;

struct node
{
    int status;
    int s[9];
    int loc;
};

int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir1[4][2] = { -1,0, 1,0, 0,-1, 0,1 };  //正方向
char op1[4] = {'u', 'd', 'l', 'r'  };
int dir2[4][2] = {0,1, 0,-1, 1,0, -1,0};    //反方向
char op2[4] = {'l', 'r', 'u', 'd'  };

char path1[MAXN], path2[MAXN];  //1为正方向,2为反方向,以下皆如此
int pre1[MAXN], pre2[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>q1, q2;
int vis1[MAXN], vis2[MAXN];
int bfs(node now)
{
    ms(vis1,0);
    ms(vis2,0);
    while(!q1.empty()) q1.pop();
    while(!q2.empty()) q2.pop();

    now.status = cantor(now.s);
    pre1[now.status] = -1;
    vis1[now.status] = 1;
    q1.push(now);

    for(int i = 0; i<9; i++)
        now.s[i] = i+1;
    now.loc = 8;
    now.status = cantor(now.s);
    pre2[now.status] = -1;
    vis2[now.status] = 1;
    q2.push(now);

    while(!q1.empty() || !q2.empty())
    {
        int s1 = q1.size(); //当前队列中的结点步数是一样的,处理完这些结点,得到步数+1的结点
        while(s1--)
        {
            now = q1.front();
            q1.pop();

            if(vis2[now.status])    //此状态已被对方访问过,则说明两者“接上了”
                return now.status;

            int x = now.loc/3;
            int y = now.loc%3;
            for(int i = 0; i<4; i++)
            {
                int xx = x + dir1[i][0];
                int yy = y + dir1[i][1];
                if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
                {
                    node tmp = now;
                    tmp.s[x*3+y] = tmp.s[xx*3+yy];
                    tmp.s[xx*3+yy] = 9;
                    tmp.status = cantor(tmp.s);
                    if(!vis1[tmp.status])
                    {
                        vis1[tmp.status] = 1;
                        tmp.loc = xx*3+yy;
                        path1[tmp.status] = op1[i];
                        pre1[tmp.status] = now.status;
                        q1.push(tmp);
                    }
                }
            }
        }

        int s2 = q2.size();
        while(s2--)
        {
            now = q2.front();
            q2.pop();

            if(vis1[now.status])    //此状态已被对方访问过,则说明两者“接上了”
                return now.status;

            int x = now.loc/3;
            int y = now.loc%3;
            for(int i = 0; i<4; i++)
            {
                int xx = x + dir2[i][0];
                int yy = y + dir2[i][1];
                if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
                {
                    node tmp = now;
                    tmp.s[x*3+y] = tmp.s[xx*3+yy];
                    tmp.s[xx*3+yy] = 9;
                    tmp.status = cantor(tmp.s);
                    if(!vis2[tmp.status])
                    {
                        vis2[tmp.status] = 1;
                        tmp.loc = xx*3+yy;
                        path2[tmp.status] = op2[i];
                        pre2[tmp.status] = now.status;
                        q2.push(tmp);
                    }
                }
            }
        }
    }
    return -1;
}

void Print1(int status) //输出正方向的路径
{
    if(pre1[status]==-1) return;
    Print1(pre1[status]);
    putchar(path1[status]);
}

void Print2(int status) //输出反方向的路径
{
    if(pre2[status]==-1) return;
    putchar(path2[status]);
    Print2(pre2[status]);
}

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 status = bfs(beg);
        if(status==-1)
            puts("unsolvable");
        else
        {
            Print1(status); Print2(status);   //输出路径
            putchar('\n');
        }
    }
}



代码三:两个队列,调用一段BFS(),用队列的大小控制“你一步, 我一步”。

#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;

struct node
{
    int status;
    int s[9];
    int loc;
};

int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir[2][4][2] = { -1,0, 1,0, 0,-1, 0,1,   0,1, 0,-1, 1,0, -1,0};  //正方向
char op[2][4] = {'u', 'd', 'l', 'r' ,   'l', 'r', 'u', 'd'  };

char path[2][MAXN];
int pre[2][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>q[2];
int vis[2][MAXN];
int bfs(int id)
{
    int Size = q[id].size();
    while(Size--)
    {
        node now = q[id].front();
        q[id].pop();

        if(vis[!id][now.status])
            return now.status;

        int x = now.loc/3;
        int y = now.loc%3;
        for(int i = 0; i<4; i++)
        {
            int xx = x + dir[id][i][0];
            int yy = y + dir[id][i][1];
            if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
            {
                node 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[id][tmp.status])
                {
                    vis[id][tmp.status] = 1;
                    tmp.loc = xx*3+yy;
                    path[id][tmp.status] = op[id][i];
                    pre[id][tmp.status] = now.status;
                    q[id].push(tmp);
                }
            }
        }
    }
    return -1;
}

int solve(node now)     //把两个bfs缩在一起写, 精简代码
{
    ms(vis,0);
    while(!q[0].empty()) q[0].pop();
    while(!q[1].empty()) q[1].pop();

    now.status = cantor(now.s);
    pre[0][now.status] = -1;
    vis[0][now.status] = 1;
    q[0].push(now);

    for(int i = 0; i<9; i++)
        now.s[i] = i+1;
    now.loc = 8;
    now.status = cantor(now.s);
    pre[1][now.status] = -1;
    vis[1][now.status] = 1;
    q[1].push(now);

    int time = 0, ret;
    while(!q[0].empty() ||!q[1].empty())
    {
        ret = bfs(0);
        if(ret!=-1) return ret;
        ret = bfs(1);
        if(ret!=-1) return ret;
        time++;
    }
    return -1;
}

void Print1(int status) //输出正方向的路径
{
    if(pre[0][status]==-1) return;
    Print1(pre[0][status]);
    putchar(path[0][status]);
}

void Print2(int status) //输出反方向的路径
{
    if(pre[1][status]==-1) return;
    putchar(path[1][status]);
    Print2(pre[1][status]);
}

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 status = solve(beg);
        if(status==-1)
            puts("unsolvable");
        else
        {
            Print1(status); Print2(status);   //输出路径
            putchar('\n');
        }
    }
}



代码四:一个队列(将正反两方向的结点都丢进同一个队列, 保证了“你一步我一步”), 一段BFS。

#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;

struct node
{
    int status;
    int s[9];
    int loc;
    int id; //id标记正反方向
};

int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir[2][4][2] = { -1,0, 1,0, 0,-1, 0,1,   0,1, 0,-1, 1,0, -1,0};  //正方向
char op[2][4] = {'u', 'd', 'l', 'r' ,   'l', 'r', 'u', 'd'  };

char path[2][MAXN];
int pre[2][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;
int vis[2][MAXN];
int bfs(node now)     //把两个bfs缩在一起写, 精简代码
{
    ms(vis,0);
    while(!que.empty()) que.pop();

    now.status = cantor(now.s);
    now.id = 0;
    pre[0][now.status] = -1;
    vis[0][now.status] = 1;
    que.push(now);

    for(int i = 0; i<9; i++)
        now.s[i] = i+1;
    now.loc = 8;
    now.status = cantor(now.s);
    now.id = 1;
    pre[1][now.status] = -1;
    vis[1][now.status] = 1;
    que.push(now);

    while(!que.empty())
    {
        node now = que.front();
        que.pop();

        if(vis[!now.id][now.status])
            return now.status;

        int x = now.loc/3;
        int y = now.loc%3;
        for(int i = 0; i<4; i++)
        {
            int xx = x + dir[now.id][i][0];
            int yy = y + dir[now.id][i][1];
            if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
            {
                node 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[now.id][tmp.status])
                {
                    vis[now.id][tmp.status] = 1;
                    tmp.loc = xx*3+yy;
                    path[now.id][tmp.status] = op[now.id][i];
                    pre[now.id][tmp.status] = now.status;
                    que.push(tmp);
                }
            }
        }
    }
}

void Print1(int status) //输出正方向的路径
{
    if(pre[0][status]==-1) return;
    Print1(pre[0][status]);
    putchar(path[0][status]);
}

void Print2(int status) //输出反方向的路径
{
    if(pre[1][status]==-1) return;
    putchar(path[1][status]);
    Print2(pre[1][status]);
}

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 status = bfs(beg);
        if(status==-1)
            puts("unsolvable");
        else
        {
            Print1(status); Print2(status);   //输出路径
            putchar('\n');
        }
    }
}





  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值