算法与数据结构(十):FIFO分支限界法(旅行商问题)(C++实现)

算法与数据结构(十):FIFO分支限界法(旅行商问题)(C++实现)

分支限界法基本思想

分支限界法常以广度优先或者最小耗费(最大效益)优先的方式搜索问题的解空间树。问题的解空间树是表示问题解空间的一颗有序树,常见的有子集树和排列树。在搜索问题的解空间树时,分支限界法和回溯法对当前扩展节点所使用的扩展方式不同。在分支限界法中,每一个活节点只有一次机会成为扩展节点。活节点一旦成为扩展节点,就一次性产生其所有儿子节点。在这些儿子节点中,那些导致不可行解或者非最优解的儿子节点被舍弃,其余儿子节点被加入活节点表中。此后,从活结点表中选取下一节点成为当前扩展节点,并重复上述节点扩展过程。这个过程一直持续到找到所求的解或活结点表为空时终止。

队列式(FIFO)分支限界法:将活节点表组织成一个队列,并按队列先进先出的原则选择下一个节点为当前扩展节点。

旅行商问题(TSP)问题

某销售员要到若干个城市销售商品,已知各个城市之间的路费(或旅费)。他要选定一条从驻地出发,经过每个城市一遍最后回到驻地的路线,使总的路线(或总的旅费最少)。

主函数
/*旅行商问题分支限界法求解*/
#include<iostream>
using namespace std;
const int NoEdge = -1;
const int MAX = 20;
int G[MAX][MAX];
int ans[MAX], x[MAX];
int bestc, cc;
void init(int n)
{
	int i, j, len;
	memset(G, NoEdge, sizeof(G));
	while (cin >> i >> j)
	{
		if (i == 0 && j == 0) break;
		cin >> len;
		G[i][j] = len;
		G[j][i] = len;
	}
	for (i = 1; i <= n; i++) x[i] = i;
	bestc = 0x7fffffff;// 0x7fffffff/INT_MAX:整数的最大值
	cc = 0;
}
void Swap(int &i, int &j)
{
	int temp;
	temp = i;
	i = j;
	j = temp;
}
void Traveling(int i, int n)
{
	int j;
	if (i == (n + 1))
	{
		if ((G[x[n - 1]][x[n]] != NoEdge) && ((cc + G[x[n]][1]) < bestc) && G[x[n]][1] != NoEdge)
		{
			for (j = 1; j < n; j++) ans[j] = x[j];
			bestc = cc + G[x[n]][1];
		}
	}
	else
	{
		for (j = i; j <= n; j++)
		{
			if ((G[x[i - 1]][x[j]] != NoEdge) && ((cc + G[x[i - 1]][x[j]]) < bestc))
			{
				Swap(x[i], x[j]);
				cc += G[x[i - 1]][x[i]];
				Traveling(i + 1, n);
				cc -= G[x[i - 1]][x[i]];
				Swap(x[i], x[j]);
			}
		}
	}
}
void print(int n)
{
	cout << "最小旅行费用为:" << bestc << endl;
	cout << "最佳路径是:";
	for (int i = 1; i <= n; i++)
		cout << ans[i] << "->";
	cout << ans[1]<<endl;
}
int main()
{
	int n;
	cout << "请输入要旅行多少个城市:" << endl;
	while (cin >> n&&n)
	{
		cout << "输入两个城市之间的距离,例如 1 2 20,输入 0 0 结束" << endl;
		init(n);
		Traveling(2, n);
		print(n);
	}
	return 1;
}

n表示总共有多少个城市,bestc存储最小的旅行费用,ans[i]存储一个最佳旅行路线。程序运行结果如下图所示:

在这里插入图片描述

参考:算法分析与设计(C++描述) 石志国、刘冀伟、姚亦飞编著
  • 3
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值