UVA 1601 POJ 3523 The Morning after Halloween 【双向BFS】【A*】 (好题)

题目链接

题意

问移动图上三个Ghost同时到达目标点的最短步数。三个Ghost可以同时移动,但不能重叠,不能交换位置。

双向BFS做法

因为状态比较多,直接BFS会T,因此用双向BFS来优化。然而直接上双向BFS还是会T,在BFS过程中枚举可以走的循环太多了,因此对图进行预处理,取出所有可以走的点进行BFS。16*16不是太多,所以没有必要hash,直接开个六维数组还方便些。其他就是一些双向BFS常规注意的地方了,比如一层一层交替更新之类的。

//UVA 1601 The Morning after Halloween
//AC 2016-7-25 11:15:26
//Two-way BFS
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <sstream>
#include <stack>
using namespace std;

#define cls(x) memset(x,0,sizeof x)
#define inf(x) memset(x,0x3f,sizeof x)
#define neg(x) memset(x,-1,sizeof x)
#define ninf(x) memset(x,0xc0,sizeof x)
#define st0(x) memset(x,false,sizeof x)
#define st1(x) memset(x,true,sizeof x)
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define bug cout<<"here"<<endl;
//#define debug

int w,h,n;
struct node
{
    int x[3],y[3];
    int steps;
    node():steps(0){cls(x);cls(y);}
    void clear(){steps=0;cls(x);cls(y);}
    node& operator= (node &rhs)
    {
        for(int i=0;i<3;++i)
        {
            x[i]=rhs.x[i];
            y[i]=rhs.y[i];
        }
        steps=rhs.steps;
        return *this;
    }
}p,q;

int G[20][20];
const int dx[]={0,-1,1,0,0};
const int dy[]={0,0,0,1,-1};
vector<pair<int,int> > GA[20][20];

inline bool legal(const node &pre,const node &now)
{
    bool res=1;
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<n;++j)
        {
            if(j!=i)
            {
                res&=(now.x[i]!=now.x[j]||now.y[i]!=now.y[j]);
                res&=!(now.x[i]==pre.x[j]&&pre.x[i]==now.x[j]&&now.y[i]==pre.y[j]&&now.y[j]==pre.y[i]);
            }
        }
    }
    return res;
}

queue<node> pque,rque;
int dist[20][20][20][20][20][20];
int visit[20][20][20][20][20][20];
#define Dist(a) dist[a.x[0]][a.y[0]][a.x[1]][a.y[1]][a.x[2]][a.y[2]]
#define Visit(a) visit[a.x[0]][a.y[0]][a.x[1]][a.y[1]][a.x[2]][a.y[2]]

int BFS()
{
    while(pque.size())pque.pop();
    while(rque.size())rque.pop();
    pque.push(p);rque.push(q);
    inf(dist);cls(visit);
    Dist(p)=Dist(q)=0;
    Visit(p)=1;Visit(q)=2;
    int li,lj,lk;
    while(pque.size()||rque.size())
    {
        if(pque.size()&&pque.size()<=rque.size())
        {
            int cur=pque.front().steps;
            while(pque.size()&&pque.front().steps==cur)
            {
                p=pque.front();pque.pop();
                vector<pair<int,int> > &g1=GA[p.x[0]][p.y[0]],&g2=GA[p.x[1]][p.y[1]],&g3=GA[p.x[2]][p.y[2]];
                li=g1.size();
                lj=(n>=2?g2.size():1);
                lk=(n==3?g3.size():1);
                for(int i=0;i<li;++i)
                {
                    for(int j=0;j<lj;++j)
                    {
                        for(int k=0;k<lk;++k)
                        {
                            if(i==j&&j==k&&i==0)
                                continue;
                            q.x[0]=g1[i].first;q.y[0]=g1[i].second;
                            if(n>=2)
                            {
                                q.x[1]=g2[j].first;
                                q.y[1]=g2[j].second;
                            }
                            if(n==3)
                            {
                                q.x[2]=g3[k].first;
                                q.y[2]=g3[k].second;
                            }
                            q.steps=p.steps+1;
                            if(legal(p,q))
                            {
                                if(Visit(q)==2)
                                    return Dist(q)+q.steps;
                                if(Visit(q)==0)
                                {
                                    if(Dist(q)>q.steps)
                                    {
                                        Dist(q)=q.steps;
                                        Visit(q)=1;
                                        pque.push(q);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        else if(rque.size())
        {
            int cur=rque.front().steps;
            while(rque.size()&&rque.front().steps==cur)
            {
                p=rque.front();rque.pop();
                vector<pair<int,int> > &g1=GA[p.x[0]][p.y[0]],&g2=GA[p.x[1]][p.y[1]],&g3=GA[p.x[2]][p.y[2]];
                li=g1.size();
                lj=(n>=2?g2.size():1);
                lk=(n==3?g3.size():1);
                for(int i=0;i<li;++i)
                {
                    for(int j=0;j<lj;++j)
                    {
                        for(int k=0;k<lk;++k)
                        {
                            if(i==j&&j==k&&i==0)
                                continue;
                            q.x[0]=g1[i].first;q.y[0]=g1[i].second;
                            if(n>=2)
                            {
                                q.x[1]=g2[j].first;
                                q.y[1]=g2[j].second;
                            }
                            if(n==3)
                            {
                                q.x[2]=g3[k].first;
                                q.y[2]=g3[k].second;
                            }
                            q.steps=p.steps+1;
                            if(legal(p,q))
                            {
                                if(Visit(q)==1)
                                    return Dist(q)+q.steps;
                                if(Visit(q)==0)
                                {
                                    if(Dist(q)>q.steps)
                                    {
                                        Dist(q)=q.steps;
                                        Visit(q)=2;
                                        rque.push(q);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}


int main()
{
    #ifdef debug
        freopen("E:\\Documents\\code\\input.txt","r",stdin);
        freopen("E:\\Documents\\code\\output.txt","w",stdout);
    #endif
    while(cin>>w>>h>>n&&w+h+n)
    {
        getchar();
        char c;
        cls(G);p.clear();q.clear();
        for(int i=0;i<h;++i)
        {
            for(int j=0;j<w;++j)
            {
                c=getchar();
                if(c=='#')G[i][j]=0;
                else
                {
                    G[i][j]=1;
                    if(c=='A')
                    {
                        p.x[0]=i;p.y[0]=j;
                    }
                    if(c=='B')
                    {
                        p.x[1]=i;p.y[1]=j;
                    }
                    if(c=='C')
                    {
                        p.x[2]=i;p.y[2]=j;
                    }
                    if(c=='a')
                    {
                        q.x[0]=i;q.y[0]=j;
                    }
                    if(c=='b')
                    {
                        q.x[1]=i;q.y[1]=j;
                    }
                    if(c=='c')
                    {
                        q.x[2]=i;q.y[2]=j;
                    }
                }
            }
            getchar();
        }
        for(int i=0;i<=h;++i)
            for(int j=0;j<=w;++j)
                GA[i][j].clear();
        int nx,ny;
        for(int i=0;i<h;++i)
        {
            for(int j=0;j<w;++j)
            {
                if(G[i][j])
                {
                    for(int k=0;k<5;++k)
                    {
                        nx=i+dx[k];ny=j+dy[k];
                        if(G[nx][ny]&&nx>=0&&nx<h&&ny>=0&&ny<w)
                            GA[i][j].push_back(make_pair(nx,ny));
                    }
                }
            }
        }
        cout<<BFS()<<endl;
    }
    return 0;
}

A*做法

(待补充……)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值