hdu1401 Solitaire双向bfs

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1401
题意:给你一个8*8的棋盘以及棋盘上有四个棋子,再给你四个棋子的位置,问你之前的四个棋子八步之内能不能走到后面的棋子的位置,一步指的是单个棋子上下左右移动到相邻的空的位置,或者若上下左右有棋子,跳过相邻的棋子到此方向的下一格(如果此处没有棋子)。
四个棋子,四个位置,可以开一个8维数组来标记这些棋子位置,同时为了减少状态,可以将四个位置先sort一下,再放进队列里面(写的时候sort写错地方,找bug找半天)。
如果单向bfs的话,到后面搜索树会很大,容易tle,用双向bfs的话,就好了。
这里写图片描述
代码:

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define scanfprint() freopen("input.txt","r",stdin)
#define printfprint() freopen("output.txt","w",stdout)
#define mem(a,b) memset(a,b,sizeof(a))
const double pi=acos(-1.0);
const int mod=1e9+7;
const double ips=0.000001;
int dir[4][2]= {0,1,0,-1,1,0,-1,0};
char flag[8][8][8][8][8][8][8][8];
struct stu
{
    int x,y;
};
struct stu1
{
    stu p[4];
    int step;
} s1,s2,s,t;
bool cmp(stu a,stu b)
{
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
bool judge_edge(int in)
{
    if(t.p[in].x==-1||t.p[in].y==-1||t.p[in].x==8||t.p[in].y==8)
        return 0;
    return 1;
}
bool judge_rep(int in)
{
    int i,j;
    for(i=0; i<4; i++)
        if(i!=in&&t.p[in].x==t.p[i].x&&t.p[in].y==t.p[i].y)
            return 0;
    return 1;
}
void make_hash(stu1 a,int value)
{
    flag[a.p[0].x][a.p[0].y] [a.p[1].x][a.p[1].y] [a.p[2].x][a.p[2].y] [a.p[3].x][a.p[3].y]=value;
}
int hash_value(stu1 a)
{
    return flag[a.p[0].x][a.p[0].y] [a.p[1].x][a.p[1].y] [a.p[2].x][a.p[2].y] [a.p[3].x][a.p[3].y];
}
bool dbfs()
{
    int in=1,sizes=0,i,j;
    queue<stu1>q[2];
    make_hash(s1,0),make_hash(s2,1);
    q[0].push(s1);
    q[1].push(s2);
    while(!q[0].empty()||!q[1].empty())
    {
        in=in^1;
        sizes=q[in].size();
        while(sizes--)
        {
            s=q[in].front();
            q[in].pop();
            if(s.step==4)
                continue;
            for(i=0; i<4; i++)
            {
                for(j=0; j<4; j++)
                {
                    t=s;
                    t.p[i].x+=dir[j][0];
                    t.p[i].y+=dir[j][1];
                    if(judge_edge(i))  //若没有边越界
                    {
                        if(!judge_rep(i))  //若这个点重复了
                        {
                            t.p[i].x+=dir[j][0];
                            t.p[i].y+=dir[j][1];
                            if(!judge_edge(i)||!judge_rep(i))//若有边越界或者重复
                                continue;
                        }
                        sort(t.p,t.p+4,cmp);
                        if(hash_value(t)==(in^1))
                            return 1;
                        if(hash_value(t)==-1)
                        {
                            t.step++;
                            make_hash(t,in);
                            q[in].push(t);
                        }
                    }
                }
            }
        }
    }
    return 0;
}
void init()
{
    memset(flag,-1,sizeof(flag));
}
int main()
{
//    scanfprint();
//    printfprint();
    int i;
    while(scanf("%d%d",&s1.p[0].x,&s1.p[0].y)!=EOF)
    {
        init();
        for(i=1; i<4; i++)
            scanf("%d%d",&s1.p[i].x,&s1.p[i].y);
        for(i=0; i<4; i++)
            scanf("%d%d",&s2.p[i].x,&s2.p[i].y);
        for(i=0; i<4; i++)
            s1.p[i].x--,s1.p[i].y--,s2.p[i].x--,s2.p[i].y--;
        sort(s1.p,s1.p+4,cmp);
        sort(s2.p,s2.p+4,cmp);
        s1.step=0,s2.step=0;
        if(dbfs())
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值