zoukankan      html  css  js  c++  java
  • HDU 3085 Nightmare Ⅱ 双向BFS

    题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步

    分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是双向BFS

    就一秒一秒走就行,男的一秒走3,女的一秒走1,然后走过的分别赋值男女标记,当走到对方的标记时就是答案了

    然后有一个不能走的地方和两个鬼的位置曼哈顿距离搞一下就行,

    注:然后涨了姿势,是队列可以直接赋值,q1=q2,以前都不知道

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int N=805;
    int T,n,m;
    int dx[4]= {0,0,1,-1};
    int dy[4]= {-1,1,0,0};
    int mp[N][N];
    char s[N][N];
    struct Point
    {
        int x,y;
    } z[2];
    queue<Point>q[3];
    int step;
    bool check(int x,int y)
    {
        if(x<1||x>n||y<1||y>m)return 0;
        if(s[x][y]=='X')return 0;
        int l1=abs(x-z[0].x)+abs(y-z[0].y);
        int l2=abs(x-z[1].x)+abs(y-z[1].y);
        if(l1<=2*step||l2<=2*step)return 0;
        return 1;
    }
    bool bfs(int pos,int num)
    {
        q[2]=q[pos];
        for(int i=0; i<num; ++i)
        {
            while(!q[2].empty())
            {
                Point a=q[2].front();
                q[2].pop();
                q[pos].pop();
                if(!check(a.x,a.y))continue;
                for(int j=0; j<4; ++j)
                {
                    int x=a.x+dx[j];
                    int y=a.y+dy[j];
                    if(!check(x,y))continue;
                    if(mp[x][y]==pos)continue;
                    if(mp[x][y]==(pos^1))return 1;
                    mp[x][y]=pos;
                    q[pos].push(Point {x,y});
                }
            }
            q[2]=q[pos];
        }
        return 0;
    }
    int solve()
    {
        int ans=-1;
        while(!q[0].empty()||!q[1].empty())
        {
            ++step;
            if(bfs(0,3)||bfs(1,1))
            {
                ans=step;
                break;
            }
        }
        return ans;
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1; i<=n; ++i)
                scanf("%s",s[i]+1);
            for(int i=0; i<3; ++i)
                while(!q[i].empty())
                    q[i].pop();
            step=0;
            int cnt=0;
            for(int i=1; i<=n; ++i)
            {
                for(int j=1; j<=m; ++j)
                {
                    mp[i][j]=-1;
                    if(s[i][j]=='M')q[0].push(Point {i,j}),mp[i][j]=0;
                    else if(s[i][j]=='G')q[1].push(Point{i,j}),mp[i][j]=1;
                    else if(s[i][j]=='Z')z[cnt].x=i,z[cnt].y=j,cnt++;
                }
            }
            printf("%d
    ",solve());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    GPRS DTU通信的本质及调试经验
    winform 控件处在中间位置
    winform 多panel编辑
    Winform 控件多闪屏问题解决方法
    int 转换 byte[] 或 byte[] 转换 int
    java 多线程(一)
    postgresql 一些操作备忘
    idea eclipse web项目
    redis 入门
    idea 版本控制
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5259445.html
Copyright © 2011-2022 走看看