您的位置:首页 > 其它

状压DP TSP不回到原点

2016-03-31 16:32 471 查看
题目大意:
有N个点,你开始在第一个点,现在要求你不重复的遍历所有点(点经过后不能再次经过),问最短距离是多少。2<=N<=16.

有N个点,你开始在第一个点,现在要求你不重复的遍历所有点(点经过后不能再次经过),问最短距离是多少。2<=N<=16.

Input

首先是一个整数N,表示有N个点,接下来是一个N*N的矩阵M,M[i][j]表示第i个点到第j个点的距离是M[i][j].

M[i][j] <= 1000.输入直到文件结尾。

Output

每个结果输出一行。

Sample Input

3
0 913 524
913 0 175
524 175 0


Sample Output

699


思路:刚开始知道是状态亚索dp,但是怎么都搞不出来。

代 码里面有注释,应该可有看懂,主要就是枚举所有状态,查看被访问的点,最后找到更有中间点替换。因为起点给定,多以从1开始循环

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 100010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 1000000000

int dp[17][(1<<17) + 5];
int mat[17][17];
int n;

int main()
{
while(scanf("%d" , &n)!=EOF)
{
//mem(dp , 0x3f);
for(int i = 0 ; i <= n  ; i ++)
for(int j = 0 ; j <= (1 << n) ; j ++) dp[i][j] = INF;
for(int i = 0 ; i < n ; i ++)
{
for(int j = 0 ; j < n ; j ++)
{
scanf("%d" , &mat[i][j]);
}
}
dp[0][1] = 0;
// for(int i = 0 ; i < n ; i ++) dp[i][1] = 0;
for(int j = 1 ; j < (1 << n ) ; j ++)    //状态
{
for(int i = 1 ; i < n ; i++)    //未被访问的点
{
if(  !(j & ( 1 << (i)) ))//
{
for(int k = 0 ; k < n ; k ++)   //中间点
{
//if(k <= i) continue;
if(dp[k][j] != INF)    //中间点被访问过
dp[i][j+(1 << (i))] = min(dp[i][j+(1 << (i))] , dp[k][j]+mat[i][k]);

}
}
}
}
// cout << dp[n-1][(1<<n)-1] << endl;
int ans = INF;
for(int i = 1 ; i < n ; i ++) ans = min(ans , dp[i][(1<<n)-1]);
cout << ans << endl;
}
return 0;
}

/*

6
0 15 62 32 15 4
15 0 456 21 35 6
62 456 0 321 12 34
32 21 321 0 123 56
15 35 12 123 0 122
21 6 34 56 122 0

88

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: