HDU 3085

转载网址:http://blog.csdn.net/u012861385/article/details/32913731


一点值得注意的,鬼魅先走,mm与gg后走,直接模拟这个这个场景,突出时间的先后性,一秒与一秒的区别。可以用曼哈顿距离来进行剪枝。

题意:有M,G两人和鬼魂(Z)在n*m的方格内,M每秒走3步,G每秒走一步,鬼魂每秒走2步,问是否能

不遇到鬼魂下两人相遇,鬼魂可以穿墙(X),人不可以。初始鬼魂有2个。



代码如下:

#include<stdio.h>  
#include<string.h>  
#include<string>  
#include<queue>  
#include<map>  
#include<iostream>  
#include<algorithm>  
#define M 800  
using namespace std;  
  
struct node  
{  
    int x,y;  
    node(){}  
    node(int xx,int yy)  
    {  
        x=xx;  
        y=yy;  
    }  
}gg,mm,zz[2],f[2][M*M];  
int step,front[2],rear[2];  
char ma[M][M];  
int n,m;  
int dir[4][2]={{-1,0},{0,1},{0,-1},{1,0}};  
bool maphaten(int x,int y)//马哈顿距离判断鬼魂是否会与人相遇  
{  
    if(x>=0&&x<n&&y>=0&&y<m&&ma[x][y]!='X')  
    {  
        for(int i=0;i<2;i++)  
        {  
            if(abs(x-zz[i].x)+abs(y-zz[i].y)<=2*step) return false;  
        }  
        return true;  
    }  
    return false;  
}  
queue<node>q[3];  
void clear()//记得清空队列  
{  
    for(int i=0;i<3;i++)  
        while(!q[i].empty())  
            q[i].pop();  
}  
bool bfs(int num,int move_step,char s,char e)//num:mm或是gg,move_step:每秒走的步数  
{  
    q[2]=q[num];//另外开个队列保存  
    for(int i=0;i<move_step;i++)  
    {  
        node u,v;  
        while(!q[2].empty())  
        {  
            u=q[2].front();  
            q[2].pop();  
            q[num].pop();  
            if(!maphaten(u.x,u.y)) continue;  
            for(int k=0;k<4;k++)  
            {  
                v=u;  
                v.x=u.x+dir[k][0];  
                v.y=u.y+dir[k][1];  
                if(!maphaten(v.x,v.y)||ma[v.x][v.y]==s) continue;  
                if(ma[v.x][v.y]==e) return true;//s与e相遇  
                ma[v.x][v.y]=s;  
                q[num].push(v);  
            }  
        }  
        q[2]=q[num];//把走了第i步的状态保存到q[2],以免重复  
    }  
    return false;  
}  
int BFS()  
{  
    step=0;  
    clear();  
    q[0].push(mm);  
    q[1].push(gg);  
    while(!q[0].empty()&&!q[1].empty())  
    {  
        step++;  
        if(bfs(0,3,'M','G')||bfs(1,1,'G','M')) return step;  
    }  
    return -1;  
}  
int main()  
{  
    int t;  
    scanf("%d",&t);  
    while(t--)  
    {  
        scanf("%d%d",&n,&m);  
        int k=0;  
        for(int i=0;i<n;i++)  
        {  
            scanf("%s",ma[i]);  
            for(int j=0;j<m;j++)  
            {  
                if(ma[i][j]=='M')  
                    mm=node(i,j);  
                else if(ma[i][j]=='G')  
                    gg=node(i,j);  
                else if(ma[i][j]=='Z')  
                    zz[k++]=node(i,j);  
            }  
        }  
        printf("%d\n",BFS());  
    }  
    return 0;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值