HDU 1401 Solitaire(双向BFS)

题目链接:Click here~~

题意:

1个8x8的棋盘有4个棋子,棋子可以上下左右走(包括跳过相邻的一个)。

给出初始状态与目标状态,问8步之内,能否到达。

解题思路:

一直听说有“双向BFS”这个词,今天终于学了。

如果单纯从1个状态开始搜索的话,每步有16种状态需要扩展,复杂度为O(16^8),不可解。

如果从2个状态同时搜,那么,每个状态只需要搜4步,复杂度为O(2*16^4),就可解了。

其他都好说,保存状态的hash值时,需要注意排序,另外开数组存hash值的话内存太大,可以用set来存hash值。

贴上代码,供大家交流吧。

其实同样的思想,这题也应该可以用dfs做,但应该比bfs慢,等有空了再写。

#include <set>
#include <queue>
#include <stdio.h>
#include <algorithm>

using namespace std;

struct Point
{
    int x,y;
    Point(){}
    Point(int x,int y):x(x),y(y){}
    bool operator < (const Point& p)const
    {
        return x<p.x || x==p.x && y<p.y;
    }
    bool operator == (const Point& p)const
    {
        return x==p.x && y==p.y;
    }
    bool Read()
    {
        return scanf("%d%d",&x,&y) != EOF;
    }
};

struct Graph
{
    Point p[4];
    bool Read()
    {
        if(!p[0].Read())
            return false;
        for(int i=1;i<4;i++)
            p[i].Read();
        return true;
    }
    int HASH()
    {
        sort(p,p+4);
        int res = 0;
        for(int i=0;i<4;i++)
        {
            int tmp = (p[i].x-1)*8 + p[i].y-1;
            res = res*64 + tmp;
        }
        return res;
    }
    bool operator == (Graph& g)
    {
        return HASH() == g.HASH();
    }
};

struct Node
{
    Graph g;
    int step;
    Node(){}
    Node(const Graph& g,int s):g(g),step(s){}
}G[2];

const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};

queue<Node> q[2];
set<int> Hash[2];

bool legal(const Point& p)
{
    return 1<=p.x && p.x<=8 && 1<=p.y && p.y<=8;
}

bool repeat(const Graph& g,const Point& p)
{
    for(int i=0;i<4;i++)
        if(g.p[i] == p)
            return true;
    return false;
}

bool bfs(int k,int layer)
{
    while(!q[k].empty() && q[k].front().step==layer)
    {
        Node T = q[k].front();
        q[k].pop();
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<4;j++)
            {
                Point next(T.g.p[i].x+dx[j], T.g.p[i].y+dy[j]);
                if(!legal(next))
                    continue;
                if(repeat(T.g,next))
                {
                    next.x += dx[j];
                    next.y += dy[j];
                    if(!legal(next) || repeat(T.g,next))
                        continue;
                }
                Node TT = T;
                TT.g.p[i] = next;
                int hash = TT.g.HASH();
                if(Hash[k^1].count(hash))
                    return true;
                if(Hash[k].count(hash))
                    continue;
                Hash[k].insert(hash);
                if(layer <= 2)
                    q[k].push(Node(TT.g,layer+1));
            }
        }
    }
    return false;
}

bool two_bfs()
{
    if(G[0].g == G[1].g)
        return true;
    for(int layer=0;layer<=3;layer++)
    {
        if(bfs(0,layer) || bfs(1,layer))
            return true;
    }
    return false;
}

void clear(queue<Node>& Q)
{
    while(!Q.empty())
        Q.pop();
}

int main()
{
    while(G[0].g.Read() && G[1].g.Read())
    {
        for(int i=0;i<=1;i++)
        {
            clear(q[i]);
            Hash[i].clear();
            Hash[i].insert(G[i].g.HASH());
            G[i].step = 0;
            q[i].push(G[i]);
        }
        puts(two_bfs()?"YES":"NO");
    }
    return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值