回家_洛谷U3427_dfs&bfs

题目描述

小H在一个划分成了n*m个方格的长方形封锁线上。 每次他能向上下左右四个方向移动一格(当然小H不可以静止不动), 但不能离开封锁线,否则就被打死了。 刚开始时他有满血6点,每移动一格他要消耗1点血量。一旦小H的 血量降到 0, 他将死去。 他可以沿路通过拾取鼠标(什么鬼。。。)来补满血量。只要他走到有鼠标的格子,他不需要任何时间即可拾取。格子上的鼠标可以瞬间补满,所以每次经过这个格子都有鼠标。就算到了某个有鼠标的格子才死去, 他也不能通过拾取鼠标补满 HP。 即使在家门口死去, 他也不能算完成任务回到家中。

地图上有 5 种格子:

数字 0: 障碍物。

数字 1: 空地, 小H可以自由行走。

数字 2: 小H出发点, 也是一片空地。

数字 3: 小H的家。

数字 4: 有鼠标在上面的空地。

小H能否安全回家?如果能, 最短需要多长时间呢?

输入格式:

第一行两个整数n,m, 表示地图的大小为n*m。

下面 n 行, 每行 m 个数字来描述地图。

输出格式:

一行, 若小H不能回家, 输出-1,否则输出他回家所需最短时间。

说明

1<=n,m<=9

分析

390分,还算好吧,毕竟从才十点多做到现在了

偷偷看了看分类发现有搜索两个小字

于是开始乱搞,bfs,dfs,枚举都上了,一直一个点过不了,TLE

一定是我的玄学优化不够到位(大雾)

并没有AC的代码

DogFS

#include <cstdio>
using namespace std;
struct loc
{
    int x,y;
};
loc st;
int n,m;
int ans=82;
int map[11][11];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
void dfs(int x,int y,int z,int w)
{
    if (!map[x][y]||!z||w>ans)
        return;
    if (map[x][y]==3&&ans<w)
    {
        ans=w;
        return;
    }
    for (int i=0;i<4;i++)
        if (map[x+dx[i]][y+dy[i]])
        {
            int t=z-1;
            if (map[x][y]==4)
            {
                t=6;
            }
            dfs(x+dx[i],y+dy[i],t,w+1);
        }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&map[i][j]);
            if (map[i][j]==2)
            {
                st.x=i;
                st.y=j;
            }
        }
    dfs(st.x,st.y,6,0);
    if (ans==82)
        ans=-1;
    printf("%d\n",ans);
    return 0;
}

BoyFS

#include <stdio.h>
#include <queue>
using namespace std;
struct state
{
    int x,y,w,z;
};
int n,m;
int map[11][11];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
bool f[11][11];
queue<state>q;
int bfs()
{
    state now,t;
    while (q.size())
    {
        t=q.front();
        for (int i=0;i<4;i++)
        {
            now.x=t.x+dx[i];
            now.y=t.y+dy[i];
            now.w=t.w-1;
            now.z=t.z+1;
            if (map[now.x][now.y]&&now.w&&!f[now.x][now.y])
            {
                f[now.x][now.y]=true;
                if (map[now.x][now.y]==4)
                {
                    f[now.x][now.y]=false;
                    now.w=6;
                }
                q.push(now);
            }
        }
        q.pop();
        if (map[t.x][t.y]==3)
        {
            return t.z;
        }
    }
    return -1;
}
int main()
{
    state st;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&map[i][j]);
            if (map[i][j]==2)
            {
                st.x=i;
                st.y=j;
                st.w=6;
                st.z=0;
                q.push(st);
                f[st.x][st.y]=true;
            }
        }
    printf("%d\n",bfs());
    return 0;
}

转载于:https://www.cnblogs.com/olahiuj/p/5781235.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值