迷宫与宝藏(bfs)(未完成)

7 篇文章 0 订阅

                                                         迷宫与宝藏

Description
机器人要在一个矩形迷宫里行动(不能原地停留,只能走向上/下/左/右),每移动一格花费1个单位时间。迷宫有以下几种元素:【*】 机器人的起点【#】 墙。机器人不能走过这些格子【.】 平地。机器人可以在上面自由行走【0-9】 宝藏。当机器人走到此处会立刻获得该数字相应的宝藏,宝藏不会消失,可以反复获取(但不能停留)若机器人要恰好获得总和为x的宝藏,它最少需要多少时间?
第一行输入任务数量T, 接下来有T个任务每块第一行有两个整数, n( < 100), m( < 100), 表示迷宫有n+1行和m+1列,输出迷宫地图。最后一行输入你要收集的宝藏的总价值x(x ≤ 100)
对于每个任务,输出最少花费的时间,如果完成不了该任务则输出-1


3

2 3
1.#2
#..#
*.#.
3

2 3
2.#2
#..#
*.#.
5

2 3
2.#2
#.3#
*.#.
5


8
-1
6



这道题写了1天,奈何学艺不精,没A掉。用了DFS加BFS,内存爆了。
思路:感觉直接用BFS情况会比较复杂,于是我像用DFS从起点开始重新搜索一遍,搜索时传回最后一个节点宝藏的数值。如果没有则传回0,这样,就得到一张新的地图,有分支的地方即为有宝藏的地方,然后用bfs进行遍历。bfs的起点应该是所有根节点汇聚的点,在DFS的时候已找出,bfs遍历的同时,在找到一处宝藏之前。机器人不能回头,如果宝藏的数值超过给定大小,则continue。
目前没过,贴一下爆内存的代码:
#include<stdio.h>
#include<queue>
using namespace std;
char mp[50][50];
int use[50][50]= {0};
int use1[50][50]={0};
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int p,n,m,ssx,ssy,tt=0;
struct node
{
    int x;
    int y;
    int my;
    int t;
    int last;
};
int jud(int e)
{
    if(e==0)return 1;
    if(e==1)return 0;
    if(e==2)return 3;
    if(e==3)return 2;
}
int dfs(int sx,int sy)
{
    node now,next;
    now.x=sx;
    now.y=sy;
    use1[now.y][now.x]=1;
    tt=0;
    for(int i=0; i<4; i++)
    {
        next.x=now.x+dir[i][0];
        next.y=now.y+dir[i][1];
        if(next.x>=0&&next.x<m+1&&next.y>=0&&next.y<n+1&&(mp[next.y][next.x]>48&&mp[next.y][next.x]<=59)&&!use1[next.y][next.x])
        {
            use[now.y][now.x]+=dfs(next.x,next.y)+mp[next.y][next.x]-48;
            if(use[now.y][now.x]!=use[next.y][next.x])
            {
                ssx=now.x;
                ssy=now.y;
                tt=0;
            }
            else tt++;
        }
        else if(next.x>=0&&next.x<m+1&&next.y>=0&&next.y<n+1&&mp[next.y][next.x]!='#'&&!use1[next.y][next.x])
        {
            use[now.y][now.x]+=dfs(next.x,next.y);
            if(use[now.y][now.x]!=use[next.y][next.x])
            {
                ssx=now.x;
                ssy=now.y;
                tt=0;
            }
            else tt++;
        }
    }
    return  use[now.y][now.x];
}
int bfs(int sx,int sy)
{
    queue<node>q;
    node now,next;
    now.x=sx;
    now.y=sy;
    now.my=0;
    now.t=tt;
    now.last=4;
    q.push(now);
    while(q.size())
    {
        now=q.front();
        for(int i=0; i<4&&i!=now.last; i++)
        {
            next.x=now.x+dir[i][0];
            next.y=now.y+dir[i][1];
            if(next.x>=0&&next.x<m+1&&next.y>=0&&next.y<n+1&&(use[next.y][next.x]!=0||(mp[next.y][next.x]>48&&mp[next.y][next.x]<=59)))
            {
                next.t=now.t+1;
                if(mp[next.y][next.x]>48&&mp[next.y][next.x]<=59)
                {
                    next.my=now.my+mp[next.y][next.x]-48;
                    next.last=4;
                }
                else
                {
                    if(mp[now.y][now.x]>48&&mp[now.y][now.x]<=59)next.last=4;
                    else next.last=jud(i);
                    next.my=now.my;
                }
                if(next.my>p)continue;
                q.push(next);
            }
            if(next.my==p)break;
        }
        if(next.my==p)break;
        q.pop();
    }
    if(q.size())return next.t;
    else return -1;
}
int main()
{
    int s,sx,sy,j;
    scanf("%d",&s);
    while(s--)
    {
        scanf("%d%d",&n,&m);
        tt=0;
        for(int i=0; i<n+1; i++)
            scanf("%s",mp[i]);
        scanf("%d",&p);
        for(int i=0; i<n+1; i++)
        {
            for(j=0; j<m+1; j++)
                {
                    use[i][j]=0;
                    use1[i][j]=0;
                }
        }
        for(int i=0; i<n+1; i++)
        {
            for(j=0; j<m+1; j++)
                if(mp[i][j]=='*')
                {
                    sx=j;
                    sy=i;
                    break;
                }
            if(mp[i][j]=='*')break;
        }
        dfs(sx,sy);
        printf("%d\n",bfs(ssx,ssy));
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值