优先队列式分支限界法解决旅行售货商问题
问题描述:
某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。
他要选定一条从驻地出发,经过每个城市一次,最后回到驻地的路线,使总的路程(或总旅费)最小。
路线是一个带权图,图中各边的费用(权)为正数。
图的一条周游路线是包括V中的每个顶点在内的一条回路。
周游路线的费用是这条路线上所有边的费用之和。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/42cbd6002af876c91158e9df16894d84.png)
带权图邻接矩阵为:
0 30 6 4
30 0 5 10
6 5 0 20
4 10 20 0
#include <bits/stdc++.h>
using namespace std;
struct node
{
int lcost;
int cc;
int rcost;
int s;
int x[5];
bool operator <(const node &a) const
{
return lcost > a.lcost;
}
};
void print(node& no, int n)
{
cout << "最优解:" << endl;
for(int i = 1; i <= n; ++i)
{
cout << no.x[i] << " ";
}
cout << endl;
cout << "最优值: " << no.lcost << endl;
}
int main()
{
int n = 4;
int a[5][5] = {{}, {0, 0, 30, 6, 4}, {0, 30, 0, 5, 10}, {0, 6, 5, 0, 20}, {0, 4, 10, 20, 0}};
int rcostSelf[5] = {};
cout << "邻接矩阵为:" << endl;
for(int i = 1; i <= 4; ++i)
{
int min = a[i][1];
for(int j = 1; j <= 4; ++j)
{
cout << setw(2) << a[i][j] << " ";
if((a[i][j] < min || min == 0)&& a[i][j] != 0)
{
min = a[i][j];
}
}
rcostSelf[i] = min;
cout << endl;
}
cout << "\n最小出度数组:" << endl;
for(int i = 1; i <= n; ++i)
{
cout << rcostSelf[i] << " ";
}
cout << "\n\n";
priority_queue<node> priQueue;
{
node firstNode;
firstNode.rcost = 0;
for(int i = 1; i <= n; ++i)
{
firstNode.rcost += rcostSelf[i];
}
firstNode.lcost = firstNode.rcost;
firstNode.cc = 0;
firstNode.s = 1;
for(int i = 1; i <= n; ++i)
{
firstNode.x[i] = i;
}
priQueue.push(firstNode);
int bestc = INT_MAX;
while(true)
{
node tmpTop = priQueue.top();
priQueue.pop();
cout << "====================\n当前活结点信息:" << endl;
cout << "层数:" << tmpTop.s << endl;
cout << "当前局部解:" << endl;
for(int i = 1; i <= tmpTop.s; ++i)
{
cout << tmpTop.x[i] << " ";
}
cout << endl;
cout << "rcost = " << tmpTop.rcost << endl;
cout << "cc = " << tmpTop.cc << endl;
cout << "lcost = " << tmpTop.lcost << endl;
cout << "====================\n" << endl;
int num = n - tmpTop.s;
if(tmpTop.s == 4)
{
print(tmpTop, n);
break;
}
for(int i = 1; i <= num; ++i)
{
node* tmp = new node;
tmp->s = tmpTop.s + 1;
for(int j = 1; j <= n; ++j)
{
tmp->x[j] = tmpTop.x[j];
}
tmp->cc = tmpTop.cc + a[tmp->x[tmpTop.s]][tmp->x[tmpTop.s + i]];
int t = tmp->x[tmpTop.s + i];
tmp->x[tmpTop.s + i] = tmp->x[tmpTop.s + 1];
tmp->x[tmpTop.s + 1] = t;
tmp->rcost = 0;
for(int j = tmpTop.s + 1; j <= n; ++j)
{
tmp->rcost += rcostSelf[tmp->x[j]];
}
if(tmp->s == n-1)
{
int bestx = tmp->cc + a[ tmp->x[n-1] ][ tmp->x[n] ] + a[ tmp->x[1] ][ tmp->x[n] ];
if(bestx < bestc)
{
bestc = bestx;
}
tmp->lcost = bestx;
}
else if(tmp->s == n)
{
tmp->lcost = tmpTop.lcost;
}
else
tmp->lcost = tmp->rcost + tmp->cc;
if(tmp->lcost > bestc)
{
cout << "减去" << endl;
continue;
}
priQueue.push(*tmp);
}
}
}
return 0;
}
最终结果:
最优解: x = {1, 4, 2, 3}
最优值: 25