HDU 1026 广度优先搜索,BFS+路径的记录

哎~~花了半天的时间写了一个DFS的程序,结果无情的limit time exceed,然后到网上搜了一下,居然用的是BFS

一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的特点是"搜到就是最优解", 而深搜用于找多个解或者是"步数已知(比如3步就必须达到条件)"的问题,它的空间效率高,但是找到的不一定是最优解,必须记录并完成整个搜索,故一般情况下,深搜需要非常高效的剪枝(优化).

像搜索最短路径这些的很明显要是用广搜,因为广搜的特性就是一层一层往下搜的,保证当前搜到的都是最优解,当然,最短路径只是一方面的应用,像什么最少状态转换也是可以应用的。
深搜就是优先搜索一棵子树,然后是另一棵,它和广搜相比,有着内存需要相对较少的优点,八皇后问题就是典型的应用,这类问题很明显是不能用广搜去解决的。或者像图论里面的找圈的算法,数的前序中序后序遍历等,都是深搜

深搜和广搜的不同之处是在于搜索顺序的不同。

深搜的实现类似于栈,每次选择栈顶元素去扩展,

广搜则是利用了队列,先被扩展的的节点优先拿去扩展。

搜索树的形态:深搜层数很多,广搜则是很宽。

深搜适合找出所有方案,广搜则用来找出最佳方案

深搜和广搜的区别:

深搜并不能保证第一次遇到目标点就是最短路径,因此要搜索所有可能的路径,因此要回溯,标记做了之后还要取消掉,因此同一个点可能被访问很多很多次。而广搜由于它的由近及远的结点扩展顺序,结点总是以最短路径被访问。一个结点如果第二次被访问,第二次的路径肯定不会比第一次的短,因此就没有必要再从这个结点向周围扩展――第一次访问这个结点的时候已经扩展过了,第二次再扩展只会得到更差的解。因此做过的标记不必去掉。因此同一个点至多只可能被访问一次。每访问一个结点,与它相连的边就被检查一次。因此最坏情况下,所有边都被检查一次,因此时间复杂度为O(E)

 BFS:

#include<stdio.h>
#include<ctype.h>
#include<queue>
#include<stack>
#include<limits.h>
#include<string.h>
#include<iostream>
using namespace std;
int
dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int
n,m;
struct
node
{

    int
time;
    int
x,y;
    int
prex,prey;
    char
data;
    bool
operator<(const node&a)const
    {

        return
a.time<time;
    }
}
s[105][105];
typedef struct
t
{

    int
x,y;
}
T;
node cur1;T cur2,next2;
int
BFS()
{

    priority_queue<node>qu;
    int
i,x1,y1;
    s[0][0].time=0;
    qu.push(s[0][0]);
    while
(!qu.empty())
    {

        cur1=qu.top();
        qu.pop();
        if
(cur1.x==n-1 && cur1.y==m-1)
            return
1;
        for
(i=0;i<4;i++)
        {

            x1=cur1.x+dir[i][0];
            y1=cur1.y+dir[i][1];
            if
(x1>=0 && x1<n && y1>=0 && y1<m)
            {

                if
(s[x1][y1].data=='.'&& s[x1][y1].time>cur1.time+1)
                {

                    s[x1][y1].time=cur1.time+1;
                    s[x1][y1].prex=cur1.x;
                    s[x1][y1].prey=cur1.y;
                    qu.push(s[x1][y1]);
                }

                else if
(isdigit(s[x1][y1].data)&& s[x1][y1].time>cur1.time+s[x1][y1].data-'0')
                {

                    s[x1][y1].time=cur1.time+s[x1][y1].data-'0'+1;
                    s[x1][y1].prex=cur1.x;
                    s[x1][y1].prey=cur1.y;
                    qu.push(s[x1][y1]);
                }
            }
        }
    }

    return
0;
}

void
printpath(int x,int y)
{

    if
(x==0&&y==0)return ;

    int
prex=s[x][y].prex;
    int
prey=s[x][y].prey;
    printpath(prex,prey);
    int
prelength=s[prex][prey].time;
    int
length=s[x][y].time;
    printf("%ds:(%d,%d)->(%d,%d)\n",prelength+1,prex,prey,x,y);
    for
(int i=prelength+2;i<=length;i++)
    {

        printf("%ds:FIGHT AT (%d,%d)\n",i,x,y);
    }
}

int
main()
{

    setbuf(stdout,NULL);
    int
i,j;
    while
(scanf("%d %d",&n,&m)!=EOF)
    {

        for
(i=0;i<n;i++)
        {

            for
(j=0;j<m;j++)
            {

                cin>>s[i][j].data;
                s[i][j].x=i;
                s[i][j].y=j;
                s[i][j].time=INT_MAX;
            }
        }

        int
state=BFS();
        if
(!state)
        {

            printf("God please help our poor hero.\n");
            printf("FINISH\n");
            continue
;
        }

        printf("It takes %d seconds to reach the target position, let me show you the way.\n",s[n-1][m-1].time);
        printpath(n-1,m-1);
        printf("FINISH\n");
    }

    return
0;
}

顺便贴一下自己超时的DFS:

#include<iostream>
#include<stdio.h>
#include<limits.h>
#include<string.h>
#include<cstdlib>
using namespace std;
int
N,M,OK;
char
map[105][105];
int
X[4]={1,-1,0,0};
int
Y[4]={0,0,1,-1};
struct
node
{

    int
prex;
    int
prey;
    int
length;
};

node visited[105][105];
void
DFS(int x,int y,int prelength)
{

    visited[x][y].length=prelength;
    if
(x==N-1&&y==M-1)
    {

        OK=1;
        return
;
    }

    for
(int i=0;i<4;i++)
    {

        int
newx=x+X[i];
        int
newy=y+Y[i];
        if
(newx>=0&&newx<N&&newy>=0&&newy<M&&map[newx][newy]!='X')
        {

            if
(map[newx][newy]=='.'&&(prelength+1<visited[newx][newy].length))
            {

                visited[newx][newy].prex=x;
                visited[newx][newy].prey=y;
                DFS(newx,newy,prelength+1);
            }
else
            if
(map[newx][newy]>'0'&& map[newx][newy]<='9')
            {

                int
stay=map[newx][newy]-'0';
                if
(prelength+stay+1<visited[newx][newy].length)
                {

                    visited[newx][newy].prex=x;
                    visited[newx][newy].prey=y;
                    DFS(newx,newy,prelength+stay+1);
                }
            }
        }
    }
}

void
printpath(int x,int y)
{

    if
(x==0&&y==0)return ;

    int
prex=visited[x][y].prex;
    int
prey=visited[x][y].prey;
    printpath(prex,prey);
    int
prelength=visited[prex][prey].length;
    int
length=visited[x][y].length;
    printf("%ds:(%d,%d)->(%d,%d)\n",prelength+1,prex,prey,x,y);
    for
(int i=prelength+2;i<=length;i++)
    {

        printf("%ds:FIGHT AT (%d,%d)\n",i,x,y);
    }

}

int
main()
{

    int
i,j;
    while
(scanf("%d %d",&N,&M)!=EOF)
    {

        OK=0;
        for
(i=0;i<N;i++)
        {

            getchar();
            for
(j=0;j<M;j++)
            {

                //cin>>map[i][j]
                scanf("%c",&map[i][j]);
                visited[i][j].prex=-1;
                visited[i][j].prey=-1;
                visited[i][j].length=INT_MAX;
            }
        }

        DFS(0,0,0);
        if
(!OK)
        {

            printf("God please help our poor hero.\n");
            printf("FINISH\n");
            continue
;
        }

        printf("It takes %d seconds to reach the target position, let me show you the way.\n",visited[N-1][M-1].length);
        printpath(N-1,M-1);
        printf("FINISH\n");
    }

    return
0;
}

你可能感兴趣的:(HDU)