1021 郊区春游 TSP+floyd
链接:https://ac.nowcoder.com/acm/contest/25022/1021
来源:牛客网
题目描述
今天春天铁子的班上组织了一场春游,在铁子的城市里有n个郊区和m条无向道路,第i条道路连接郊区Ai和Bi,路费是Ci。经过铁子和顺溜的提议,他们决定去其中的R个郊区玩耍(不考虑玩耍的顺序),但是由于他们的班费紧张,所以需要找到一条旅游路线使得他们的花费最少,假设他们制定的旅游路线为V1, V2 ,V3 ... VR,那么他们的总花费为从V1到V2的花费加上V2到V3的花费依次类推,注意从铁子班上到V1的花费和从VR到铁子班上的花费是不需要考虑的,因为这两段花费由学校报销而且我们也不打算告诉你铁子学校的位置。
输入描述:
第一行三个整数n, m, R(2 ≤ n ≤ 200, 1 ≤ m ≤ 5000, 2 ≤ R ≤ min(n, 15))。i
第二行R个整数表示需要去玩耍的郊区编号。
以下m行每行A
, Bi
, Ci
(1 ≤ Ai
, Bi
≤ n, Ai
≠ Bi
, Ci
≤ 10000)
保证不存在重边。
输出描述:
输出一行表示最小的花费
分析
最终改了inf = 0x3f3f3f3f过了。。0x7f7f7f7f都不管用
TSP类型的问题,我一开始还以为所有结点都要走,不管看了 n 的范围:200,怎么都不可能啊。最后发现是先floyd预处理处所有 目标旅游景点之间的距离,再在他们之间用 TSP。。
设dp[st] [j] 表示状态是st ,最后一步走到j 的最短距离。
枚举 起始位置和新位置,st 满足没有新位置有起始位置就可以了
状态转移:
dp[i | (1 <<(k-1)] [k] = min(dp[i | ( 1 << (k-1)][k],dp[i][j] + a[i][j]); a表示两点最短距离。
//-------------------------代码---------------------------- //#define int ll const int N = 400; int n,m,r; int a[N][N]; int rs[N]; int dp[1 << 20][20]; void solve() { cin>>n>>m>>r; for(int i=1;i<=r;i++) cin>>rs[i]; ms(a,inf); ms(dp,inf); while(m--) { int u,v,w; cin>>u>>v>>w; a[u][v]=a[v][u]=w; } for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) a[i][j]=min(a[i][j],a[i][k]+a[k][j]); } } for(int i=1;i<=r;i++) { dp[1<<(i-1)][i]=0; //最开始走的那一个点,是没有花费的 } for(int i=1;i<(1<<r)-1;i++)//枚举状态 { for(int j=1;j<=r;j++)//枚举起始位置 { int jj=1<<(j-1); if(!(i&jj)) continue;//起始位置肯定是走过的 for(int k=1;k<=r;k++)//枚举终止位置 { int kk=1<<(k-1); if(i&kk) continue;//终止位置一定是一个新位置 dp[i|kk][k]=min(dp[i|kk][k],dp[i][j]+a[rs[j]][rs[k]]); } } } int mn = inf; fo(i,1,r) { mn = min(mn,dp[(1<<r)-1][i]); } cout<<mn<<endl; } signed main(){ AC(); clapping();TLE; // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------