原题链接: ​​ http://acm.hdu.edu.cn/showproblem.php?pid=1026​


一:题意

一个n*m的矩阵代表一个迷宫,(0,0)是起点,(n-1)(m-1)是终点,每移动一步一秒。

迷宫每点意义是:

.   该点可以走

X 该点不可以走

n  在该点停留n秒(其中1<=n<=9)

若可以到达终点,求起点到终点的最小秒,并输出路径。


二:分析

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

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

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

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

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

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

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

深搜和广搜的区别:

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


三:AC代码

#define _CRT_SECURE_NO_DEPRECATE 
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

#include<iostream>
#include<algorithm>
#include<functional>
#include<vector>
#include<queue>

using namespace std;

int n, m;
int dir[4][2] = { { 0,1 },{ 0,-1 },{ 1,0 },{ -1,0 } };
struct Node
{
int time;
int x, y;
int prex, prey;
char ch;

bool operator>(const Node & node) const
{
return time > node.time;
}

}node[105][105];

bool BFS()
{
int i;
int mx, my;
Node cur;
priority_queue<Node, vector<Node>, greater<Node> > pq;

node[0][0].time = 0;
pq.push(node[0][0]);

while (!pq.empty())
{
cur = pq.top();
pq.pop();
if (cur.x == n - 1 && cur.y == m - 1)
return true;
for (i = 0; i < 4; i++)
{
mx = cur.x + dir[i][0];
my = cur.y + dir[i][1];
if (mx >= 0 && mx < n&&my >= 0 && my < m)
{
if (node[mx][my].ch == '.'&&node[mx][my].time > cur.time + 1)
{
node[mx][my].time = cur.time + 1;
node[mx][my].prex = cur.x;
node[mx][my].prey = cur.y;
pq.push(node[mx][my]);
}
else if (node[mx][my].ch >= '1'&&node[mx][my].ch <= '9'&&node[mx][my].time > cur.time + node[mx][my].ch - '0'+1)//注意这里加1
{
node[mx][my].time = cur.time + node[mx][my].ch - '0' + 1;//注意这里加1
node[mx][my].prex = cur.x;
node[mx][my].prey = cur.y;
pq.push(node[mx][my]);
}
}
}
}

return false;
}

void printPath(int x, int y)
{
if (x == 0 && y == 0)
return;

int prex = node[x][y].prex;
int prey = node[x][y].prey;

printPath(prex, prey);

int prelength = node[prex][prey].time;
int length = node[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()
{

int i, j;
while (~scanf("%d%d", &n, &m))
{
for (i = 0; i < n; i++)
{
getchar();
for (j = 0; j < m; j++)
{
scanf("%c", &node[i][j].ch);
node[i][j].time = INT_MAX;
node[i][j].x = i;
node[i][j].y = j;
}
}


bool 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", node[n - 1][m - 1].time);
printPath(n - 1, m - 1);
printf("FINISH\n");
}


return 0;
}