码迷,mamicode.com
首页 > 编程语言 > 详细

哈密尔顿回路(旅行售货员问题)的回溯算法

时间:2016-07-23 15:21:47      阅读:284      评论:0      收藏:0      [点我收藏+]

标签:

1. 回溯法的基本原理:

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为:

1、定义一个解空间,它包含问题的解。

2、利用适于搜索的方法组织解空间。

3、利用深度优先法搜索解空间。

4、利用限界函数避免移动到不可能产生解的子空间。

问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。

2.旅行售货员问题的回溯算法实现

算法具体实现主要代码如下:

// TravelSaler.cpp : 定义控制台应用程序的入口点。

//

//旅行员售货员问题 回溯法求解

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include<stdlib.h>

using namespace std;

?

ifstream fin("input.txt");

const int N = 4;//图的顶点数

?

template<class Type>

class Traveling

{

????template<class Type>

????friend Type TSP(Type **a, int n);

private:

????void Backtrack(int i);

????int n,???????? // 图G的顶点数

????????*x, // 当前解

????????*bestx; // 当前最优解

????Type **a, // 图G的领接矩阵

????????cc, // 当前费用

????????bestc; // 当前最优值

????int NoEdge; // 无边标记

};

?

template <class Type>

inline void Swap(Type &a, Type &b);

?

template<class Type>

Type TSP(Type **a, int n);

?

int main()

{

????cout << "图的顶点个数 n=" << N << endl;

?

????int **a = new int*[N + 1];

????for (int i = 0; i <= N; i++)

????{

????????a[i] = new int[N + 1];

????}

?

????cout << "图的邻接矩阵为:" << endl;

?

????for (int i = 1; i <= N; i++)

????{

????????for (int j = 1; j <= N; j++)

????????{

????????????fin >> a[i][j];

????????????cout << a[i][j] << " ";

????????}

????????cout << endl;

????}

????cout << "最短回路的长为:" << TSP(a, N) << endl;

?

????for (int i = 0; i <= N; i++)

????{

????????delete[]a[i];

????}

????delete[]a;

?

????a = 0;

????system("pause");

????return 0;

????

}

?

template<class Type>

void Traveling<Type>::Backtrack(int i)

{

????if (i == n)

????{

????????if (a[x[n - 1]][x[n]] != 0 && a[x[n]][1] != 0 &&

????????????(cc + a[x[n - 1]][x[n]] + a[x[n]][1] < bestc || bestc == 0))

????????{

????????????for (int j = 1; j <= n; j++) bestx[j] = x[j];

????????????bestc = cc + a[x[n - 1]][x[n]] + a[x[n]][1];

????????}

????}

????else

????{

????????for (int j = i; j <= n; j++)

????????{

????????????// 是否可进入x[j]子树?

????????????if (a[x[i - 1]][x[j]] != 0 && (cc + a[x[i - 1]][x[i]] < bestc || bestc == 0))

????????????{

????????????????// 搜索子树

????????????????Swap(x[i], x[j]);

????????????????cc += a[x[i - 1]][x[i]]; //当前费用累加

????????????????Backtrack(i + 1);????????????//排列向右扩展,排列树向下一层扩展

????????????????cc -= a[x[i - 1]][x[i]];

????????????????Swap(x[i], x[j]);

????????????}

????????}

????}

}

?

template<class Type>

Type TSP(Type **a, int n)

{

????Traveling<Type> Y;

????Y.n = n;

????Y.x = new int[n + 1];

????Y.bestx = new int[n + 1];

?

????for (int i = 1; i <= n; i++)

????{

????????Y.x[i] = i;

????}

?

????Y.a = a;

????Y.cc = 0;

????Y.bestc = 0;

?

????Y.NoEdge = 0;

????Y.Backtrack(2);

?

????cout << "最短回路为:" << endl;

????for (int i = 1; i <= n; i++)

????{

????????cout << Y.bestx[i] << " --> ";

????}

????cout << Y.bestx[1] << endl;

?

????delete[] Y.x;

????Y.x = 0;

????delete[] Y.bestx;

?

????Y.bestx = 0;

????return Y.bestc;

}

?

template <class Type>

inline void Swap(Type &a, Type &b)

{

????Type temp = a;

????a = b;

????b = temp;

}

其中input.txt的内容为:

0 30 6 4

30 0 5 10

6 5 0 20

4 10 20 0

编译并运行程序。

3. 旅行售货员问题的回溯算法的解空间树以及搜索过程:

技术分享

3)算法的时间复杂性和空间复杂性

?算法backtrack在最坏情况下可能需要更新当前最优解O((n-1)!)次,每次更新bestx需计算时间O(n),从而整个算法的计算时间复杂性为O(n!)?

程序运行结果如下:

技术分享

?

开始测试时每次都要输入图的邻接矩阵,非常麻烦,后面改为直接从input文件中读取,大大简化了调试过程

哈密尔顿回路(旅行售货员问题)的回溯算法

标签:

原文地址:http://www.cnblogs.com/leftshine/p/5698557.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!