2631: 回溯法-旅行售货商问题
金币值:3
定数:8
时间限制:1.000 s
内存限制:128 M
正确:4
提交:4
正确率:100.00% 命题人:
题目描述
某售货员要到若干城市去推销商品,已知各城市之间的路程或旅费(如果两个城市之间无路直接相通,则认为路程或话费为无穷大)。要求他选定一条从驻地出发,经过每个城市一遍且仅一遍,最后回到驻地的路线,使的总的路程或总旅费最小。
测试代码 复制
# include <stdio.h>
#define infinity 0x7fffffff // 表示无穷大
#define MAX 20 //表示城市的最大个数
int G[MAX+1][MAX+1]; //邻接矩阵,0号单元不存储信息
int bestx[MAX+1]; //最优解,0号单元不存储信息
int x[MAX+1]; //当前解,0号单元不存储信息
int m,n; //n表示图中顶点(城市)个数,m表示图中边的个数
int bestc;//最小成本
int cc; //当前成本
void createGraph(){
int i,j,k,w;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++){ //初始化邻接矩阵
for(j=1;j<=n;j++){
G[i][j]=infinity;
}
}
for(k=1;k<=m;k++){ //输入边的信息修改邻接矩阵
scanf("%d %d %d",&i,&j,&w);
G[i][j]=w;
G[j][i]=w;
}
}
void swap(int& x, int& y){
int t=x;
x=y;
y=t;
}
void Traveling(int i){
int j;
if(i==n+1){
if(G[x[n]][1]!=infinity && (cc+G[x[n]][1]<bestc)){
//如果x[n]与x[1]之间有边相连且当前费用加上该边的权小
//于当前找到的最优值,则找到了一个更好的解并做相应的更新操作
}
}
else{
for(j=i;j<=n;j++){
//如果约束条件成立(x[i-1]和x[j]有边相连)和限界
//条件成立(当前费用加上下一条边上的权小于当前最好值),
//则交换下标为i的结点和下标为j的结点
if(G[x[i-1]][x[j]]!=infinity && (cc+G[x[i-1]][x[j]]<bestc)){
}
}
}
}
void output(){
int i;
printf("%d\n",bestc);
//旅行售货商问题是一个环路,从某个顶点出发最后还要回到该顶点
for(i=1;i<=n;i++) printf("%d->",bestx[i]);
printf("%d\n",bestx[1]);
}
int main(void){
createGraph();
for(int i=1;i<=n;i++) x[i]=i; //初始化解向量
bestc=infinity; //初始化最优成本为无穷大
cc=0; //初始化当前成本
Traveling(2);
// 从排列树中的第2层开始搜索,因为本题是一个特殊的排
// 列树(x[1]的值为1且不发生变化)
output();
return 0;
}
输入格式
第一行输入两个整数,分别表示图中的顶点(城市)个数和边的个数(如果两个城市之间有路直接相通,则有一条加权边,边上的权表示两个城市之间的路程或旅费)
输出格式
第一行输出最少费用
第二行输出对应于最少费用的最佳推销商品路径(从顶点1出发,最后回到顶点1,详见案例输出)
第二行输出对应于最少费用的最佳推销商品路径(从顶点1出发,最后回到顶点1,详见案例输出)
输入样例 复制
4 6
1 2 30
1 3 4
1 4 6
2 3 10
2 4 5
3 4 20
输出样例 复制
25
1->3->2->4->1