旅行商问题动态规划解法(不到10行解决)

首先简略介绍一下旅行商问题:有n个城市,相互之间有一条路径,但距离大小不同,求从某个城市 c 出发访问所有城市一次后回到 c 的最短距离。

博主另一篇文章毕业旅行省钱问题其实也是这个问题的一个解法,那边的编程思想是图的深度遍历。今天给大家介绍一种动态规划解法,本文的程序编写是受到这位大神的文章启发,有兴趣的同学也可以去看看。

回到旅行商的一个具体问题,假如有城市 c_0c_1c_2c_3,要从 c_0 开始访问所有城市一遍后回到 c_0,求这个路径最短的回路长度。

动态规划解法思路:要去的城市集合用 S 表示,S=\left \{ c_1, c_2, c_3 \right\},问题用 P(c_0, S) 表示,可理解为从 c_0 出发访问 S 中所有的城市后回到 c_0 的最短路径,它的解是 D(c_0, c_1)+P(c_1, S-c_1)D(c_0, c_2)+P(c_2, S-c_2)D(c_0, c_3)+P(c_3, S-c_3) 中最小的一个,其中D(c_i, c_j)表示 c_i 城市与 c_j 城市之间的距离,可以列出状态转移方程:

P(c_i, S)=\begin{cases} D(c_i, c_0)& \text{ if } S=\emptyset \\ \min \limits_{c_j\in S} \left \{D(c_i, c_j)+P(c_j, S-c_j) \right \}& \text{ if } S\not=\emptyset \end{cases}

根据这个思路进行编程,代码如下:

class Solution2{
public:
	int SearchLowestPricePath(int amount, int startCity=0){
		if(amount>32)
			return -1;
		int s=(1<<(amount-1))-1;
		/*生成城市之间的路径图,对称矩阵*/
		v=new int* [amount];
		for(int i=0; i<amount; i++)
			v[i]=new int [amount];
		int n=amount;
		for(int i=0;i<amount; i++){
			for(int j=i; j<amount; j++){
				v[i][j]=v[j][i]=(j==i) ? 0:(rand()%10+1);
			}
		}
        /*调用旅行商算法*/
		TSP(startCity, s);
	}

	int TSP(int curCity, int S){//S存储要去的城市,这里用到了二进制的技巧,假如有3个城市C1、C2、C3要去,111表示都要去;101表示c1、c3要去,c2不用去
		if(S==0) return v[curCity][0];
		int optVal=INT_MAX;
		int t=S;
		while(t){
			int b=log(~(t-1)&t)/log(2), nextCity=b+1, S1=S-(1<<b);
			optVal=min(optVal, TSP(nextCity,S1)+v[curCity][nextCity]);
			t=(t-1)&t;
		}
		return optVal;
	}
private:
	int** v;
};



int main()
{
	Solution2 c;
	c.SearchLowestPricePath(5);//方法调用,5个城市
	system("pause");
	return 0;
}

核心函数TSP是不是不到10行就实现了呢~欢迎大家发表评论

发布了18 篇原创文章 · 获赞 0 · 访问量 788

猜你喜欢

转载自blog.csdn.net/afiguresomething/article/details/103281228
今日推荐