深度搜索的应用----环路最小路径

环路最小路径问题:就是熟称的旅行者问题,也叫TSP算法。

假设有五个城市A,B,C,D,E。如果旅行者从A城市出发,历经其它各个城市,最终又回到A城市,且其中每个城市只能经过一次。求环路中最短的路径就是所谓的旅行者问题。我们依旧可以采取DFS的算法解决该问题。

本题的思路是利用深度搜索进行穷举,把所有的路径都走一次,找到一个最短的路径。当然中途可以剪支。

要求输入,例如:

5         
9 9 2 9 5
6 3 5 1 5
1 8 3 3 3
6 0 9 6 8
6 6 9 4 8

第一行表示一共有5个城市,其实形成一个5×5的邻接矩阵

后面的2~6行表示每个城市和每个城市的距离,可以理解为有向带权图,其中0表示从i城市出发到第j城市是走不通的,即不存在连通性

要求输出:最小的距离,例如:

18


代码部分:

  1. #include <iostream>
  2. using namespace std;
  3. int answer;
  4. int N;
  5. int Array[12][12];
  6. int visit[12];
  7. int result;
  8. //深度搜索
  9. void DFS(int node)
  10. {
  11.     visit[node] = 1;
  12.     int tmpDis = answer;
  13.     //判断是否所有的节点都被访问过了
  14.     int isAllVisit = false;
  15.     int i;
  16.     for (i = 0; i < N; ++i)
  17.     {
  18.         //找到node节点和i节点是否存在连通性,且i节点是没有被访问过的,即没有被走过的
  19.         if (Array[node][i] != 0 && visit[i] != 1)
  20.         {
  21.             //如果到达该节点的路径,已经比记录过的最小值还大,就不走这条路,换条路走;
  22.             answer = tmpDis + Array[node][i];
  23.             if (answer > result)
  24.             {
  25.                 continue;
  26.             }
  27.             DFS(i);
  28.         }
  29.     }
  30.     int j;
  31.     for (j = 0; j < N; ++j)
  32.     {
  33.         if (visit[j] == 0)
  34.         {
  35.             isAllVisit = false;
  36.             break;
  37.         }
  38.         isAllVisit = true;
  39.     }
  40.     //如果所有的通路都被走过了,而且从最后一个节点回到0节点是有通路的,就算出此时的最小距离
  41.     if (true == isAllVisit && Array[node][0])
  42.     {
  43.         answer = answer + Array[node][0];
  44.         //如果比之前记录下的距离还小就保存起来,否则还是上次保存的最小距离
  45.         if (result>answer)
  46.         {
  47.             result = answer;
  48.         }
  49.     }
  50.     //还原走过的节点,为别的还可能存在的路径做准备
  51.     visit[node] = 0;
  52. }
  53. int main(int argc, char** argv)
  54. {
  55.     int i, j;
  56.     cin >> N;
  57.     //初始化邻接矩阵和visit数组
  58.     for (i = 0; i < N; ++i)
  59.     {
  60.         for (j = 0; j < N; ++j)
  61.         {
  62.             cin >> Array[i][j];
  63.         }
  64.         visit[i] = 0;
  65.     }
  66.     //初始化最短距离和最终的结果,假定result开始之前是无穷大,我们用0x7fffff表示
  67.     answer = 0;
  68.     result = 0x7fffff;
  69.     DFS(0);
  70.    
  71.     cout << result << endl;
  72.     return 0;
  73. }

最后同样给出几组测试数据:

5         

9 9 2 9 5

6 3 5 1 5

1 8 3 3 3

6 0 9 6 8

6 6 9 4 8

10

1 2 5 3 1 2 2 3 1 1

2 3 5 4 3 6 3 1 3 2

4 1 3 2 7 4 2 7 2 1

3 6 4 4 3 6 6 6 6 1

3 6 5 2 3 1 3 3 2 1

4 4 4 5 3 5 6 2 7 2

3 5 2 1 4 4 7 5 7 4

1 1 6 1 3 4 6 7 5 2

1 4 5 1 7 5 5 5 2 1

2 4 2 1 1 2 2 3 4 2

9

0 6 2 8 8 5 8 7 4

9 0 4 3 2 0 5 8 3

4 4 0 1 0 4 5 3 2

4 9 7 0 0 3 8 9 6

8 6 1 5 0 9 3 6 2

7 1 5 4 9 0 6 4 1

0 8 6 5 3 9 0 6 2

5 9 8 2 0 9 3 0 9

9 0 3 2 1 0 3 5 0

10

0 29 61 43 43 2 67 22 2 19

29 0 7 9 69 63 70 66 37 26

61 7 0 71 8 49 65 57 91 5

43 9 71 0 39 16 13 38 36 69

43 69 8 39 0 61 66 83 27 10

2 63 49 16 61 0 49 38 97 24

67 70 65 13 66 49 0 19 55 21

22 66 57 38 83 38 19 0 49 48

2 37 91 36 27 97 55 49 0 31

19 26 5 69 10 24 21 48 31 0

10

0 39 55 41 71 92 43 10 95 73

39 0 20 22 75 25 92 12 14 89

55 20 0 91 47 34 21 24 21 4

41 22 91 0 12 45 44 36 45 86

71 75 47 12 0 48 29 19 22 10

92 25 34 45 48 0 34 17 55 14

43 92 21 44 29 34 0 20 36 48

10 12 24 36 19 17 20 0 75 67

95 14 21 45 22 55 36 75 0 96

73 89 4 86 10 14 48 67 96 0

结果分别为:

18 15 23 132 183



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值