hdu1072(dfs和bfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1072

题意:有一个n*m的矩阵迷宫,2是起点,3是终点,0是墙不能走,1是路,现在有6分钟炸弹要爆炸,没走一步花一分钟,问你是否能到达终点

能,则输出最短时间,不能输出-1。而4是重置时间,将时间变为6分钟,注意的是,不能正好时间为0,到达终点或者重置时间。

bfs的思路比较简单,就是从起点开始搜索。遇到终点则就是最短时间,遇到4(重置设备)时间变为6分钟,并将此地方变为墙,因为每个重置设备在保证时间最短的情况下,只会有一次,如果返回来多次使用,只会增加消耗的时间,不会增加可花费的时间。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node{
    int x,y,step,time;
};
int map[10][10],n,m;
int bx,by;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
void bfs()
{
    queue<node>q;
    node t={bx,by,0,6};//起点的状态
    q.push(t);
    while(!q.empty())
    {
        node p;
        p=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            t.x=dx[i]+p.x;
            t.y=dy[i]+p.y;
            t.step=p.step+1;
            t.time=p.time-1;
            if(t.x>=0&&t.x<n&&t.y>=0&&t.y<m&&t.time>0&&map[t.x][t.y]!=0)//可行走的情况
            {
                if(map[t.x][t.y]==3)//到达终点,就是最短时间
                {
                    cout<<t.step<<endl;
                    return ;
                }
                if(map[t.x][t.y]==4)//遇到重置设备
                {
                    t.time=6;
                    map[t.x][t.y]=0;
                }
                q.push(t);
            }
        }
    }
    cout<<-1<<endl;//始终没有搜索到终点,不能到达
    return ;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                cin>>map[i][j];
                if(map[i][j]==2)
                {
                    bx=i,by=j;//起点
                }
            }
        }
        bfs();
    }
    return 0;
}

而dfs的思路稍微复杂些,要考虑用重置设备后要返回的情况。但是我们可以知道如果要重复走走过的路,他的消耗时间一定多了,但剩下的时间一定要比原来多才有用。要不然剩下的时间少了,消耗的时间多了,谁会干着这种吃力不讨好的事?

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,map[10][10],step[10][10],time[10][10],flag,ans;
int bx,by,ex,ey;
void dfs(int x,int y,int sum,int T)//sum为花费时间,T为还剩的时间
{
    if(T<=0||map[x][y]==0||x<0||x>=n||y<0||y>=m)//不合法和不可行的情况
        return ;
    //cout<<x<<" "<<y<<endl;
    if(x==ex&&y==ey)//遇到终点
    {
        flag=1;//标记
        ans=min(ans,sum);//取最小时间
        return ;
    }
    if(map[x][y]==4)//遇到重置设备
        T=6;
    if(sum>=step[x][y]&&time[x][y]>=T)//走已经走过的路,但剩下的时间少于原来的时间就不会走
        return  ;
    step[x][y]=sum;//更新这一步的消耗时间和剩余时间
    time[x][y]=T;
    dfs(x,y-1,sum+1,T-1);//左
    dfs(x,y+1,sum+1,T-1);//右
    dfs(x-1,y,sum+1,T-1);//下
    dfs(x+1,y,sum+1,T-1);//上
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        flag=0;
        ans=inf;
        cin>>n>>m;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                time[i][j]=0;
                step[i][j]=inf;
                cin>>map[i][j];
                if(map[i][j]==2)//起点
                {
                    bx=i;
                    by=j;
                }
                if(map[i][j]==3)//终点
                {
                    ex=i;
                    ey=j;
                }
            }
        dfs(bx,by,0,6);
        if(flag==0)
            cout<<-1<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/xiongtao/p/9382143.html

时间: 2024-12-12 13:26:28

hdu1072(dfs和bfs)的相关文章

学习笔记:图的DFS和BFS的两种搜索办法

  在学习图结构的过程中,DFS和BFS是两种不同的遍历方式,其寻找元素具有不同的优点和缺陷. BFS被称作广度优先算法, 在遍历整个图的过程中,BFS将采用入队的方式进行,值得一提的是,这和树结构中的层序遍历有很大的相似之处. 在层序遍历中,将父亲节点入队后,在父亲节点出队后,将其儿子节点入队. 同理在图的BFS遍历中,先让BFS的首元素入队,在收元素入队后将他的儿子节点入队,放能够实现BFS搜索,他们的整体思想是一样的. 1 void TraversalGraph_BFS(LGraph Gr

递归,回溯,DFS,BFS的理解和模板【摘】

递归:就是出现这种情况的代码: (或者说是用到了栈) 解答树角度:在dfs遍历一棵解答树 优点:结构简洁缺点:效率低,可能栈溢出 递归的一般结构: 1 void f() { 2 if(符合边界条件) { 3 /////// 4 return; 5 } 6 7 //某种形式的调用 8 f(); 9 } 回溯:递归的一种,或者说是通过递归这种代码结构来实现回溯这个目的.回溯法可以被认为是一个有过剪枝的DFS过程.解答树角度:带回溯的dfs遍历一棵解答树回溯的一般结构: 1 void dfs(int

搜索分析(DFS、BFS、递归、记忆化搜索)

搜索分析(DFS.BFS.递归.记忆化搜索) 1.线性查找 在数组a[]={0,1,2,3,4,5,6,7,8,9,10}中查找1这个元素. (1)普通搜索方法,一个循环从0到10搜索,这里略. (2)递归(从中间向两边) 1 //递归一定要写成记忆化递归 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool vis[11]; 5 int count1=0; 6 7 void search(int n){ 8 count1++; 9

数据结构(11) -- 邻接表存储图的DFS和BFS

/////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS /////////////////////////////////////////////////////////////// #include <iostream> #include <stdlib.h> #include <queue> using namespace std; //图的邻接表表示法

PAT 05-1 List Components (简单DFS与BFS)

刚一拿到这道题把他想的太复杂了 明明是长度最大为十的顺序结构就能解决的问题,竟然优先想到用链表. BFS牵扯到一个队列的操作,在这种小规模数据里面 用顺序结构好很多 题目如下: For a given undirected graph with N vertices and E edges, please list all the connected components by both DFS and BFS. Assume that all the vertices are numbered

hdu 4707 Pet(dfs,bfs)

Pet Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1548    Accepted Submission(s): 733 Problem Description One day, Lin Ji wake up in the morning and found that his pethamster escaped. He sear

数据结构(12) -- 图的邻接矩阵的DFS和BFS

//////////////////////////////////////////////////////// //图的邻接矩阵的DFS和BFS //////////////////////////////////////////////////////// #include <iostream> #include <stdlib.h> #include <queue> #define MaxVertexNum 100 //最大顶点数 //#define INFINI

POJ 1426 Find The Multiple(DFS,BFS)

Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100

在DFS和BFS中一般情况可以不用vis[][]数组标记

开始学dfs 与bfs 时一直喜欢用vis[][]来标记有没有访问过, 现在我觉得没有必要用vis[][]标记了 看代码 用'#'表示墙,'.'表示道路 if(所有情况都满足){ map[i][j]='#'; dfs(i,j); map[i][j]='.';} 一般情况都可以这样做.