在这一篇博客:http://blog.csdn.net/hacker_zhidian/article/details/54773762中我们通过一道全排列的例子看了一下深度优先搜索(dfs)的基本思想和代码模型,这里我们再通过一道题目来加深dfs思想的理解:
有一个迷宫,迷宫状态通过一个二维数组储存,给出二维数组的行总数和列总数和对应坐标的数据,求出从开始点(坐标为0,0)到结束点(最后一行给出的点的坐标)所需的最短路径,样例数据: 5 4 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 3 2
利用dfs解决这道题我们依然需要使用标记数组来标记迷宫之中某个点的状态(是否已经走过),如果没有走过就可以走这个点,否则就要筛选下一个点,当然我们还需要判断迷宫边界,要走的点不能越界,那么,我们可以架构出大致的代码(将行作为x坐标,列作为y坐标):
int next[4][2] = { // 代表下一步的4个走向
{-1, 0}, // 上
{0, 1}, // 右
{1, 0}, // 下
{0, -1} // 左
};
for(int i = 0; i < 4; i++)
{
nX = x + next[i][0];
nY = y + next[i][1]; // 下一步可能的坐标
if(nX < 0 || nX >= 总行数 || nY < 0 || nY >= 总列数) // 判断是否越界
{
continue;
}
if(book[nX][nY] == 0) // 如果这个坐标点没有走过
{
book[nX][nY] = 1; // 标记这个点已经走过
到达(nX, nY)点并继续筛选
book[nX][nY] = 0; // 取消标记这个点,用于下一轮的尝试
}
}
当我们到达目标点之后就可以结束筛选了,那么我们如何储存最短路径呢,当然是当我们到达了目标点的时候来进行最短路径的比较了,下面给出完整代码:
#include <iostream>
using namespace std;
int n = 5, m = 4; // 迷宫信息的二维数组的总行数和总列数
int map[100][100] = {
{0, 0, 1, 0},
{0, 0, 0, 0},
{0, 0, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 1}
}; // 储存迷宫信息的二维数组
int toX = 3, toY = 2; // 目标点
int book[100][100]; // 标记数组
int ans = 100000000; // 最短路径的结果
int next[4][2] = { // 代表下一步的4个走向
{-1, 0}, // 上
{0, 1}, // 右
{1, 0}, // 下
{0, -1} // 左
};
void dfs(int x, int y, int sum)
{
if(x == toX && y == toY) //如果到达了目标点,则比较路径长短
{
if(ans > sum) // 如果当前路径小于当前的最短路径,则替换
{
ans = sum;
}
return ;
}
int nX, nY; // 下一步的坐标
for(int i = 0; i < 4; i++)
{
nX = x + next[i][0];
nY = y + next[i][1]; // 下一步可能的坐标
if(nX < 0 || nX >= n || nY < 0 || nY >= m) // 判断是否越界
{
continue;
}
if(book[nX][nY] == 0 && map[nX][nY] == 0) // 如果这个坐标点没有走过并且可以通过
{
book[nX][nY] = 1; // 标记这个点已经走过
dfs(nX, nY, sum + 1); // 继续筛选下一个位置,经过的路径数加一
book[nX][nY] = 0; // 取消标记这个点,用于下一轮的尝试
}
}
}
int main()
{
cin >> n >> m;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
cin >> map[i][j];
}
}
cin >> toX >> toY;
book[0][0] = 1; // 第一个走过的点标记
dfs(0, 0, 0);
cout << ans << endl;
return 0;
}
运行结果:
结果正如我们所料,哈哈。 如果有什么不对的地方,还请指点。 谢谢观看。。。