1.代码:
#include <stdio.h>
#include <malloc.h>
#define NoEdge 1000
struct MinHeapNode
{
int lcost; //子树费用的下界
int cc; //当前费用
int rcost; //x[s:n-1]中顶点最小出边费用和
int s; //根节点到当前节点的路径为x[0:s]
int *x; //需要进一步搜索的顶点是//x[s+1:n-1]
struct MinHeapNode *next;
};
int n; //图G的顶点数
int **a; //图G的邻接矩阵
//int NoEdge; //图G的无边标记
int cc; //当前费用
int bestc; //当前最小费用
MinHeapNode* head = 0; /*堆头*/
MinHeapNode* lq = 0; /*堆第一个元素*/
MinHeapNode* fq = 0; /*堆最后一个元素*/
int DeleteMin(MinHeapNode*&E)
{
MinHeapNode* tmp = NULL;
tmp = fq;
// w = fq->weight ;
E = fq;
if(E == NULL)
return 0;
head->next = fq->next; /*一定不能丢了链表头*/
fq = fq->next;
// free(tmp) ;
return 0;
}
int Insert(MinHeapNode* hn)
{
if(head->next == NULL)
{
head->next = hn; //将元素放入链表中
fq = lq = head->next; //一定要使元素放到链中
}else
{
MinHeapNode *tmp = NULL;
tmp = fq;
if(tmp->cc > hn->cc)
{
hn->next = tmp;
head->next = hn;
fq = head->next; /*链表只有一个元素的情况*/
}else
{
for(; tmp != NULL;)
{
if(tmp->next != NULL && tmp->cc > hn->cc)
{
hn->next = tmp->next;
tmp->next = hn;
break;
}
tmp = tmp->next;
}
}
if(tmp == NULL)
{
lq->next = hn;
lq = lq->next;
}
}
return 0;
}
int BBTSP(int v[])
{//解旅行售货员问题的优先队列式分支限界法
/*初始化最优队列的头结点*/
head = (MinHeapNode*)malloc(sizeof(MinHeapNode));
head->cc = 0;
head->x = 0;
head->lcost = 0;
head->next = NULL;
head->rcost = 0;
head->s = 0;
int *MinOut = new int[n + 1]; /*定义定点i的最小出边费用*/
//计算MinOut[i]=顶点i的最小出边费用
int MinSum = 0;//最小出边费用总合
for(int i = 1; i <= n; i++)
{
int Min = NoEdge; /*定义当前最小值*/
for(int j = 1; j <= n; j++)
if(a[i][j] != NoEdge && /*当定点i,j之间存在回路时*/
(a[i][j] < Min || Min == NoEdge)) /*当顶点i,j之间的距离小于Min*/
Min = a[i][j]; /*更新当前最小值*/
if(Min == NoEdge)
return NoEdge;//无回路
MinOut[i] = Min;
//printf("%d\n",MinOut[i]);/*顶点i的最小出边费用*/
MinSum += Min;
// printf("%d\n",MinSum); /*最小出边费用的总和*/
}
MinHeapNode *E = 0;
E = (MinHeapNode*)malloc(sizeof(MinHeapNode));
E->x = new int[n];
// E.x=new int[n];
for(int i = 0; i < n; i++)
E->x[i] = i + 1;
E->s = 0;
E->cc = 0;
E->rcost = MinSum;
E->next = 0; //初始化当前扩展节点
int bestc = NoEdge; /*记录当前最小值*/
//搜索排列空间树
while(E->s < n - 1)
{//非叶结点
if(E->s == n - 2)
{//当前扩展结点是叶结点的父结点
/*
首先考虑s=n-2的情形,此时当前扩展结点是排列树中某个叶结点的父结点。如果该叶结点相应一条可行回路
且费用小于当前最小费用,则将该叶结点插入到优先队列中,否则舍去该叶结点
*/
if(a[E->x[n - 2]][E->x[n - 1]] != NoEdge && /*当前要扩展和叶节点有边存在*/
a[E->x[n - 1]][1] != NoEdge && /*当前页节点有回路*/
(E->cc + a[E->x[n - 2]][E->x[n - 1]] + a[E->x[n - 1]][1] < bestc /*该节点相应费用小于最小费用*/
|| bestc == NoEdge))
{
bestc = E->cc + a[E->x[n - 2]][E->x[n - 1]] + a[E->x[n - 1]][1]; /*更新当前最新费用*/
E->cc = bestc;
E->lcost = bestc;
E->s++;
E->next = NULL;
Insert(E); /*将该页节点插入到优先队列中*/
}else
free(E->x);//该页节点不满足条件舍弃扩展结点
}else
{/*产生当前扩展结点的儿子结点
当s<n-2时,算法依次产生当前扩展结点的所有儿子结点。由于当前扩展结点所相应的路径是x[0:s],
其可行儿子结点是从剩余顶点x[s+1:n-1]中选取的顶点x[i],且(x[s],x[i])是所给有向图G中的一条边。
对于当前扩展结点的每一个可行儿子结点,计算出其前缀(x[0:s],x[i])的费用cc和相应的下界lcost。
当lcost<bestc时,将这个可行儿子结点插入到活结点优先队列中。*/
for(int i = E->s + 1; i < n; i++)
if(a[E->x[E->s]][E->x[i]] != NoEdge)
{ /*当前扩展节点到其他节点有边存在*/
//可行儿子结点
int cc = E->cc + a[E->x[E->s]][E->x[i]]; /*加上节点i后当前节点路径*/
int rcost = E->rcost - MinOut[E->x[E->s]]; /*剩余节点的和*/
int b = cc + rcost; //下界
if(b < bestc || bestc == NoEdge)
{//子树可能含最优解,结点插入最小堆
MinHeapNode * N;
N = (MinHeapNode*)malloc(sizeof(MinHeapNode));
N->x = new int[n];
for(int j = 0; j < n; j++)
N->x[j] = E->x[j];
N->x[E->s + 1] = E->x[i];
N->x[i] = E->x[E->s + 1];/*添加当前路径*/
N->cc = cc; /*更新当前路径距离*/
N->s = E->s + 1; /*更新当前节点*/
N->lcost = b; /*更新当前下界*/
N->rcost = rcost;
N->next = NULL;
Insert(N); /*将这个可行儿子结点插入到活结点优先队列中*/
}
}
free(E->x);
}//完成结点扩展
DeleteMin(E);//取下一扩展结点
if(E == NULL)
break; //堆已空
}
if(bestc == NoEdge)
return NoEdge;//无回路
for(int i = 0; i < n; i++)
v[i + 1] = E->x[i];//将最优解复制到v[1:n]
while(true)
{//释放最小堆中所有结点
free(E->x);
DeleteMin(E);
if(E == NULL)
break;
}
return bestc;
}
int main()
{
n = 0;
int i = 0;
//FILE *in, *out;
//in = fopen("input.txt", "r");
//out = fopen("output.txt", "w");
//if(in == NULL || out == NULL)
//{
// printf("没有输入输出文件\n");
// return 1;
//}
//fscanf(in, "%d", &n);
n=5;
a = (int**)malloc(sizeof(int*) * (n + 1));
for(i = 1; i <= n; i++)
{
a[i] = (int*)malloc(sizeof(int) * (n + 1));
}
// for(i = 1; i <= n; i++)
// for(int j = 1; j <= n; j++)
// //fscanf(in, "%d", &a[i][j]);
// a[i][j]=1;
a[1][1]=0;
a[1][2]=5;
a[1][3]=8;
a[1][4]=5;
a[1][5]=4;
a[2][1]=5;
a[2][2]=0;
a[2][3]=5;
a[2][4]=6;
a[2][5]=3;
a[3][1]=8;
a[3][2]=5;
a[3][3]=0;
a[3][4]=5;
a[3][5]=4;
a[4][1]=5;
a[4][2]=6;
a[4][3]=6;
a[4][4]=0;
a[4][5]=3;
a[5][1]=4;
a[5][2]=3;
a[5][3]=4;
a[5][4]=3;
a[5][5]=0;
// prev = (int*)malloc(sizeof(int)*(n+1)) ;
int*v = (int*)malloc(sizeof(int) * (n + 1));// MaxLoading(w , c , n) ;
for(i = 1; i <= n; i++)
v[i] = 0;
bestc = BBTSP(v);
printf("\n");
for(i = 1; i <= n; i++)
fprintf(stdout, "%d\t", v[i]);
fprintf(stdout, "\n");
fprintf(stdout, "%d\n", bestc);
return 0;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
2.输出结果