题意:有中文版的
分析:(出题人的解题报告)我们首先需要预处理出任意两个国家之间的最短距离,因为数据范围很小,所以直接用Floyd就行了。之后,我们用f[S][i]表示访问国家的情况为S,当前最后访问的一个国家是i所需要的最小总油量,其中,S的二进制表示记录了访问国家的情况,S在二进制表示下的第i位(不管是从左往右还是从右往左都可以)如果是1则表示第i个国家被访问过了,否则表示第i个国家没有被访问过,那么f[S|(1<<i)][i]=min(f[S][j]+f[i][j]),其中i和j满足S&(1<<j)=1且S&(1<<i)=0。最开始时,除了f[1][1]是0,其他情况都是无穷大,之后先枚举S,再枚举i(我验题的时候因为这里搞反结果WA了),那么最终的答案就是min(f[(1<<n)-1][i]+f[i][1]),其中iin∈[2,n]。总复杂度为O(n^3+n^2*2^n)O(n3+n2∗2n)。
收获:暂时无,TSP没搞懂纯贴模板
代码:
/************************************************ * Author :Running_Time * Created Time :2015-8-22 18:55:17 * File Name :B.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int d[17][17]; int dp[(1<<16)+10][17]; int n, m; int work(void) { for (int k=0; k<n; ++k) { for (int i=0; i<n; ++i) { for (int j=0; j<n; ++j) { d[i][j] = min (d[i][j], d[i][k] + d[k][j]); } } } for (int i=0; i<(1<<n); ++i) { for (int j=0; j<n; ++j) dp[i][j] = INF; } dp[1][0] = 0; for (int i=0; i<(1<<n); ++i) { for (int j=0; j<n; ++j) { if (dp[i][j] != INF) { for (int k=0; k<n; ++k) { if (!(i>>k&1)) { dp[i|(1<<k)][k] = min (dp[i|(1<<k)][k], dp[i][j] + d[j][k]); } } } } } int ans = INF; for (int i=0; i<n; ++i) { ans = min (ans, dp[(1<<n)-1][i] + d[i][0]); } return ans; } int main(void) { int T; scanf ("%d", &T); while (T--) { scanf ("%d%d", &n, &m); for (int i=0; i<n; ++i) { for (int j=0; j<n; ++j) d[i][j] = INF; } for (int u, v, w, i=1; i<=m; ++i) { scanf ("%d%d%d", &u, &v, &w); u--, v--; d[u][v] = min (d[u][v], w); d[v][u] = min (d[v][u], w); } for (int i=0; i<n; ++i) d[i][i] = 0; printf ("%d ", work ()); } return 0; }