这是我从一本书上看的的一道题,特来与大家分享,如下:
假设有5个城市编号为1,2,3,4,5,它们之间的关系为如图
图中<-表示公路,<-上的数字为距离,并且公路为单向公路,如1城市与5城市之间关系为:从1可以到5,距离为10km,但不能从5到1,其他类似。
现在有个人住在1城市,他想去拜访住在5城市的朋友,求他所走的最短距离(不需要求路径)。
对于这个问题我们就可以使用
深度优先探索的方法,深度优先探索的意思是我们在这一步可以干什么,有几个选择,选择其中一个可能后,再到下一步可以干什么,有几个选择,直到达到目的,但这只是其中的一条路,我们需要找出其他的可能性,这就需要返回。深度优先探索就是一步一步都试图走完所有的点,尝试所有的可能性。如:
我们是从1开始,1城市可以到2城市和5城市,我们选择5城市,达到目的并算出距离返回,在尝试走2城市,并且标记2城市已走过,防止陷入死循坏,就这样一步一步的尝试完所有的可能性,在每次达到目的后把这个方法所需的距离与保存的最小距离比较,最后输出最小距离。
从题目中我们我们可以得到一个关系表:
2个城市之间没有公路连接表示为-1,有则表示位之间的距离,每个城市到自己的距离为0;
| 1 | 2 | 3 | 4 | 5 |
1 | 0 2 -1 -1 10
2 | -1 0 3 -1 7
3 | 4 -1 0 4 -1
4 | -1 -1 -1 0 5
5 | -1 -1 3 -1 0
我们可以定义一个二维数组来保存这个表格:
int a[5][5] = {
{ 0, 2, -1, -1, 10 },
{ -1, 0, 3, -1, 7 },
{ 4, -1, 0, 4, -1 },
{ -1, -1, -1, 0, 5 },
{ -1, -1, 3, -1, 0 }
};
我们还需要定义一个标记数组来标记这个城市是否已走过:
int sign[5] = { 0 };
定义一个全局变量来保存最小距离:
int min = 999999;
核心代码为一个递归函数,全部代码如下:
#include
int a[5][5] = {
{ 0, 2, -1, -1, 10 },
{ -1, 0, 3, -1, 7 },
{ 4, -1, 0, 4, -1 },
{ -1, -1, -1, 0, 5 },
{ -1, -1, 3, -1, 0 }
};
int sign[5] = { 0 };
int min = 999999;
void find_( int x, int count )
{
//判断是否已经到达5城市
if( x == 4 )
{
if( count < min )
{
min = count;//更新min值
return;
}
}
int i = 0;
//寻找所有的可能性,并且尝试所有的可能性并移动到可以移动的城市
for( i = 0; i < 5; i++ )
{
//这个城市与上个城市之间连通且之前并没有走过,就移动到这个城市
if( a[x][i] > 0 && sign[i] == 0 )
{
sign[i] = 1;//标记这个城市已走过
count += a[x][i];
find_( i, count );//移动到下个城市,寻找目标
sign[i] = 0;//返回后取消标记,防止其他路径出现错误
count -= a[x][i];//这一步很重要,要将count的值还原
}
}
}
int main()
{
sign[0] = 1;
find_( 0, 0 );
printf("min = %d", min );
getchar();
getchar();
return 0;
}
运行结果为:
除了用深度优先探索这个方法,我们还可以用广度优先探索,在这里我先大家推荐一本书《啊哈!算法》,这是一本很棒的书,推荐大家去看。