TSP问题
Time Limit: 5000 ms Memory Limit: 65535 KBTotal Submit: 163 Accepted: 83
Description
旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。
Input
第一行输入一个整数n(2<=n<=15)。
接下来的n行,每行输入n-1个整数xj(0<xj<=500),表示i与除了自己之外的所以点之间的距离,按点的编号从小到大的顺序输入。
接下来的n行,每行输入n-1个整数xj(0<xj<=500),表示i与除了自己之外的所以点之间的距离,按点的编号从小到大的顺序输入。
Output
输出一行,就是所有路径之中的最小值。
Sample Input
5
3 1 5 8
3 6 7 9
1 6 4 2
5 7 4 3
8 9 2 3
4
3 6 7
5 2 3
6 4 2
3 7 5
3 1 5 8
3 6 7 9
1 6 4 2
5 7 4 3
8 9 2 3
4
3 6 7
5 2 3
6 4 2
3 7 5
Sample Output
16
10
10
这段代码的集合使用二进制来表示的,需要注意的就是集合的枚举顺序。由于是用二进制表示的,则可以发现这样一个规律,如果a是b的真子集,则相对应的二进制数一定有a<b。因此若以集合递增的顺序计算,需要用到某个d值是,它一定是在之前已经计算出来的。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include<map>
#define pi acos(-1.0)
#define eps 1e-6
#define inf 1<<30
#define INF 1ll<<60
#define ll long long
using namespace std;
int n;
int maps[20][20];
int d[20][1<<16];
int main()
{
int a;
while(cin>>n)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
if(i==j)
{
maps[i][i]=inf;
continue;
}
int a;
cin>>a;
maps[i][j]=a;
}
}
for(int i=0; i<n; i++)
for(int s=0; s<(1<<n); s++)
d[i][s]=inf;
for(int s=0; s<(1<<n-1); s++)
{
for(int i=0; i<n; i++)
{
if(s==0)
d[i][s]=maps[i][0];
for(int j=1; j<n; j++)
{
if(s&(1<<(j-1)))
d[i][s]=min(d[i][s],d[j][s^(1<<(j-1))]+maps[i][j]);
}
}
}
// for(int i=0; i<n; i++)
// {
// for(int s=0; s<(1<<(n-1)); s++)
//
// cout<<d[i][s]<<" ";
// cout<<endl;
// }
cout<<d[0][(1<<n-1)-1]<<endl;
}
return 0;
}