【题目链接】:click here~~
【题目大意】:
问题描写叙述
经过多年的努力,Victor最终考到了飞行驾照。 为了庆祝这件事,他决定给自己买一架飞机然后环游世界。 他会驾驶一架飞机沿着规定的航线飞行。在地球上一共同拥有nn个国家,编号从11到nn。各个国家之间通过mm条双向航线连接,第ii条航线连接第u_iu?i??个国家与第v_iv?i??个国家,通过这条航线须要消耗w_iw?i??升油。且从11号国家能够直接或间接到达22到nn中随意一个国家。 Victor一開始位于11号国家。他想知道从11号国家出发,经过各个国家至少一次并最后回到11号国家消耗的总油量的最小值是多少。
输入描写叙述
第一行包括一个整数TT,表示測试数据的组数。 每组測试数据的第一行有两个整数nn和mm,表示国家的个数和航线的条数。 接下来mm行。每行三个整数u_iu?i??, v_iv?i??, w_iw?i??,描写叙述一条航线。 1\leq T\leq 201≤T≤20。 1\leq n\leq 161≤n≤16。 1\leq m\leq 1000001≤m≤100000。 1\leq w_i\leq 1001≤w?i??≤100。 1\leq u_i, v_i \leq n1≤u?i??,v?i??≤n。
输出描写叙述
每组測试数据输出一行一个整数,即消耗的总油量的最小值。
输入例子
1 3 2 1 2 2 1 3 3
输出例子
10
【思路】:
我们首先须要预处理出随意两个国家之间的最短距离。由于数据范围非常小,所以直接用Floyd即可了。
之后,我们用f[S][i]表示訪问国家的情况为S,当前最后訪问的一个国家是i所须要的最小总油量,当中,S的二进制表示记录了訪问国家的情况,S在二进制表示下的第i位(无论是从左往右还是从右往左都能够)假设是1则表示第i个国家被訪问过了,否则表示第i个国家没有被訪问过。那么f[S|(1<<i)][i]=min(f[S][j]+mat[i][j])(mat[i][j]:表示城市i,j的最短路径)。当中i和j满足S&(1<<j)=1且S&(1<<i)=0。
最開始时,除了f[1][1]是0,其它情况都是无穷大,之后先枚举S,再枚举i,那么终于的答案就是min(f[(1<<n)-1][i]+f[i][1]),当中i\in∈[2,n]。总复杂度为O(n^3+n^2*2^n)O(n?3??+n?2???2?n??)。
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <fstream> #include <cstring> #include <climits> #include <deque> #include <cmath> #include <queue> #include <stack> #include <ctime> #include <list> #include <map> #include <set> #include <utility> #include <sstream> #include <complex> #include <string> #include <vector> #include <cstdio> #include <bitset> #include <functional> #include <algorithm> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<(int)k;++i) #define per(i,j,k) for(int i=(int)j;i>(int)k;--i) #define lowbit(a) a&-a #define Max(a,b) a>b?a:b #define Min(a,b) a>b?b:a #define mem(a,b) memset(a,b,sizeof(a)) const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; const int N=1e5+100; const double eps = 1e-15; typedef long long LL; typedef unsigned long long ULL; typedef pair <int, int> pir; int mat[100][100]; int dp[(1<<16)+10][20]; int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}}; int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}}; int movv[5][2]= {{1,0},{0,1},{0,0},{-1,0},{0,-1}}; inline LL read() { int c=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){c=c*10+ch-‘0‘;ch=getchar();} return c*f; } int main(){ int t;t=read(); while (t--){ mem(dp,inf);mem(mat,inf); int u, v, w, n, m; n=read();m=read(); for(int i = 1; i <= m; ++i){ u=read();v=read();w=read();--u;--v; mat[u][v] = Min(mat[u][v], w); mat[v][u] = Min(mat[v][u], w); } for (int i = 0; i < n; ++i){ mat[i][i] = 0; } for (int k = 0; k < n; ++k){// floyd for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ mat[i][j] = Min(mat[i][j], mat[i][k] + mat[k][j]); } } } dp[0][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){ dp[i | (1 << k)][k] = Min(dp[i | (1 << k)][k], dp[i][j] + mat[j][k]); } } } } printf("%d\n", dp[(1 << n) - 1][0]); } return 0; } /* 1 3 2 1 2 2 1 3 3 */
时间: 2024-10-16 03:38:32