java贪心算法旅行售货员问题_回溯法之旅行售货员问题

本文介绍了如何使用Java实现回溯法来解决旅行售货员问题,详细阐述了算法描述、代码实现及测试样例,旨在找到最短路径。
摘要由CSDN通过智能技术生成

问题描述:

某售货员要到若干城市去推销商品,已知各城市之间的路程,他要选定一条从驻地出发,经过每个城市一遍,最后回到住地的路线,使总的路程最短。

算法描述:

回溯法,序列树, 假设起点为 1。

算法开始时 x = [1, 2, 3, ..., n]

x[1 : n]有两重含义 x[1 : i]代表前 i 步按顺序走过的城市, x[i + 1 : n]代表还未经过的城市。利用Swap函数进行交换位置。

若当前搜索的层次i = n 时,处在排列树的叶节点的父节点上,此时算法检查图G是否存在一条从顶点x[n-1] 到顶点x[n] 有一条边,和从顶点x[n] 到顶点x[1] 也有一条边。若这两条边都存在,则发现了一个旅行售货员的回路即:新旅行路线),算法判断这条回路的费用是否优于已经找到的当前最优回路的费用bestcost,若是,则更新当前最优值bestcost和当前最优解bestx。

若i < n 时,检查x[i - 1]至x[i]之间是否存在一条边, 若存在,则x [1 : i ] 构成了图G的一条路径,若路径x[1: i] 的耗费小于当前最优解的耗费,则算法进入排列树下一层,否则剪掉相应的子树。

代码实现:

#include

using namespacestd;const int max_ = 0x3f3f3f;const int NoEdge = -1;intcitynum;intedgenum;intcurrentcost;intbestcost;int Graph[100][100];int x[100];int bestx[100];voidInPut()

{intpos1, pos2, len;

scanf("%d %d", &citynum, &edgenum);

memset(Graph, NoEdge,sizeof(Graph));for(int i = 1; i <= edgenum; ++i)

{

scanf("%d %d %d", &pos1, &pos2, &len);

Graph[pos1][pos2]= Graph[pos2][pos1] =len;

}

}voidInitilize()

{

currentcost= 0;

bestcost=max_;for(int i = 1; i <= citynum; ++i)

{

x[i]=i;

}

}void Swap(int &a, int &b)

{inttemp;

temp=a;

a=b;

b=temp;

}void BackTrack(int i) //这里的i代表第i步去的城市而不是代号为i的城市

{if(i ==citynum)

{if(Graph[x[i - 1]][x[i]] != NoEdge && Graph[x[i]][x[1]] != NoEdge && (currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]] < bestcost || bestcost ==max_))

{

bestcost= currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]];for(int j = 1; j <= citynum; ++j)

bestx[j]=x[j];

}

}else{for(int j = i; j <= citynum; ++j)

{if(Graph[x[i - 1]][x[j]] != NoEdge && (currentcost + Graph[x[i - 1]][x[j]] < bestcost || bestcost ==max_))

{

Swap(x[i], x[j]);//这里i 和 j的位置交换了, 所以下面的是currentcost += Graph[x[i - 1]][x[i]];

currentcost += Graph[x[i - 1]][x[i]];

BackTrack(i+ 1);

currentcost-= Graph[x[i - 1]][x[i]];

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

}

}

}

}voidOutPut()

{

cout<< "路线为:" <

cout<< bestx[i] << " ";

cout<< "1" <

}intmain()

{

InPut();

Initilize();

BackTrack(2);

OutPut();

}

View Code

测试样例:

实现结果:

参考:王晓东《算法设计与分析》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值