zl程序教程

您现在的位置是:首页 >  其它

当前栏目

刷题记录:牛客NC16122郊区春游

记录 刷题 牛客
2023-09-14 09:12:55 时间

传送门:牛客

题目描述:

今天春天铁子的班上组织了一场春游,在铁子的城市里有n个郊区和m条无向道路,第i条道路连接郊区Ai和Bi,
路费是Ci。经过铁子和顺溜的提议,他们决定去其中的R个郊区玩耍(不考虑玩耍的顺序),但是由于他们的班
费紧张,所以需要找到一条旅游路线使得他们的花费最少,假设他们制定的旅游路线为V1, V2 ,V3 ... VR,那么
他们的总花费为从V1到V2的花费加上V2到V3的花费依次类推,注意从铁子班上到V1的花费和从VR到铁子班上
的花费是不需要考虑的,因为这两段花费由学校报销而且我们也不打算告诉你铁子学校的位置。
输入:
4 6 3
2 3 4
1 2 4
2 3 3
4 3 1
1 4 1
4 2 2
3 1 6
输出:
3

但是对于本题来说,我感觉题目讲的并不是很清楚,首先它并没有说确保存在只有上述几个点的回路,但是照通过的代码来看是默认确保的,所以我的代码和讲解也是默认确保的

一道经典的TSP问题,对于此题,若不太清楚先去看看博主的本篇文章,在这篇文章中,对TSP进行了完备的介绍.

然后对于此题,首先我们应该明白,我们可以使用floyd求出每一个节点之间的最短距离.这样的话对于每一个点来说只要经过一次就可以了,因为两点之间已经是最短距离了,走多次只会花更多的时间,所以本题就转化成了经典的TSP问题,直接套上即可

然后对于本题来说,因为是不用回到最开始的地方的,所以使用顺推的解决方法比倒推更为容易,并且因为刚开始可以任选源点,所以我们应当将刚开始只有一个节点的状态的花费赋值为0,对于最终的答案找一个最小值即可

下面是具体的代码部分:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
#include <deque>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps=1e-8;
int m,n,r;int mp[220][220];int Want_go[220];int dp[1<<16][16];
int main() {
	memset(mp,0x3f,sizeof(mp));
	memset(dp,0x3f,sizeof(dp));
	n=read();m=read();r=read();
	for(int i=0;i<r;i++) Want_go[i]=read();
	for(int i=1;i<=m;i++) {
		int u=read(),v=read(),w=read();
		mp[u][v]=min(mp[u][v],w);
		mp[v][u]=mp[u][v];
	}
	for(int k=1;k<=n;k++) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) {
				if(i==j) continue;
				mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
			}
		}
	}
	for(int i=0;i<r;i++) dp[1<<i][i]=0;
	for(int S=1;S<(1<<r);S++) {
		for(int u=0;u<r;u++) {
			if(!((S>>u)&1)) continue;
			for(int v=0;v<r;v++) {
				if((S>>v)&1) continue;
				dp[S|(1<<v)][v]=min(dp[S|(1<<v)][v],dp[S][u]+mp[Want_go[u]][Want_go[v]]);
			}
		}
	}
	int ans=inf;
	for(int i=0;i<r;i++) {
		ans=min(ans,dp[(1<<r)-1][i]);
	}
	cout<<ans<<endl;
	return 0;
}