hdu2531Catch him(bfs)

->题目请戳这里<-

题目大意:中文题,很简单,自己看。

题目分析:本题也是迷宫搜索类的,不过和一般的迷宫问题不一样的是本题的搜索者有着庞大的身躯,所以一步要占几个格子。不过这对我们的搜索策略并无多大影响,我们只需在移动的时候将搜索者身体所占的地方同时向一个方向移动就可以了。本题要求最少步数,故用bfs。搜索者的身体不超过20格,用结构体保存搜索者的身体信息,从起点开始搜。搜索前先想好判重问题,由于本题给的是100*100的地图,所以我给每个格子编号,第i行j列的格子编号i*m+j,m是地图的列,然后每个节点加一个val值,代表当前搜索者所占位置的编号和,仔细想想,搜索者身体是不变的,因此不同位置会有不同的val值,可以估计最大的val值不会超过20万。详情请见代码:

#include <iostream>
#include<cstdio>
#include<queue>

using namespace std;
const int N = 105;
char map[N][N];
bool flag[200000];
int n,m;
int dire[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};//右,左,上,下
struct node
{
    int i[21],j[21];
    int num,val,step;
}s,now;
queue<struct node>myque;
int ok;

int isok(int id)
{
    int mark = 0;
    int i;
    s.val = 0;
    for(i = 0;i < s.num;i ++)
    {
        s.i[i] += dire[id][0];
        s.j[i] += dire[id][1];
        s.val += (s.i[i] * m + s.j[i]);
        if(s.i[i] < 0 || s.i[i] >= n || s.j[i] < 0 || s.j[i] >= m)
            return 0;
        if(map[s.i[i]][s.j[i]] == 'O')
            return 0;
        if(map[s.i[i]][s.j[i]] == 'Q')
            mark = 1;
    }
    if(mark)
        ok = 1;
    return 1;
}

void bfs()
{
    while(!myque.empty())
        myque.pop();
    int i;
    //printf("%d\n",s.val);
    myque.push(s);
    flag[s.val] = 1;
    while(!myque.empty())
    {
        now = myque.front();
        myque.pop();
        for(i = 0;i < 4;i ++)
        {
            s = now;
            if(isok(i) && !flag[s.val])
            {
                flag[s.val] = 1;
                s.step = now.step + 1;
                if(ok)
                {
                    printf("%d\n",s.step);
                    return ;
                }
                //printf("%d\n",s.val);
                myque.push(s);
            }
        }
    }
    printf("Impossible\n");
}

int main()
{
    int i,j;
    while(scanf("%d%d",&n,&m),(m + n))
    {
        getchar();
        s.val = s.num = s.step = 0;
        for(i = 0;i < n;i ++)
        {
            for(j = 0;j < m;j ++)
            {
                map[i][j] = getchar();
                if(map[i][j] == 'D')
                {
                    s.i[s.num] = i;
                    s.j[s.num] = j;
                    s.num ++;
                    s.val += (i * m + j);
                }
            }
            getchar();
        }
        memset(flag,0,sizeof(flag));
        ok = 0;
        bfs();
    }
    return 0;
}
//15MS	580K
/*
5 6
...Q..
.O.O..
......
..OO.O
....DD
*/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值