郊区春游(状压dp)
作者:互联网
链接:https://ac.nowcoder.com/acm/contest/134/D
来源:牛客网
今天春天铁子的班上组织了一场春游,在铁子的城市里有n个郊区和m条无向道路,第i条道路连接郊区Ai和Bi,路费是Ci。经过铁子和顺溜的提议,他们决定去其中的R个郊区玩耍(不考虑玩耍的顺序),但是由于他们的班费紧张,所以需要找到一条旅游路线使得他们的花费最少,假设他们制定的旅游路线为V1, V2 ,V3 ... VR,那么他们的总花费为从V1到V2的花费加上V2到V3的花费依次类推,注意从铁子班上到V1的花费和从VR到铁子班上的花费是不需要考虑的,因为这两段花费由学校报销而且我们也不打算告诉你铁子学校的位置。
链接:https://ac.nowcoder.com/acm/contest/134/D
来源:牛客网
输入描述:
第一行三个整数n, m, R(2 ≤ n ≤ 200, 1 ≤ m ≤ 5000, 2 ≤ R ≤ min(n, 15))。
第二行R个整数表示需要去玩耍的郊区编号。
以下m行每行A
i
, B
i
, C
i
(1 ≤ A
i
, B
i
≤ n, A
i
≠ B
i
, C
i
≤ 10000)
保证不存在重边。
输出描述:
输出一行表示最小的花费示例1
输入
复制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
状压dp,dp[ s ][ i ]表示当前已经游玩的点(R中的点),且终点是 i 的最小花费。预处理出任意两点之间的最短距离。
其中s指的是状态,
比如dp[5][j]的5二进制是101,就是表示当前走过的路径上的目标郊区有0,2,dp[8][j]的话就是有目标郊区3
#include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn=1e3+100; const int inf=0x3f3f3f3f; /* dp[s][i]表示当前已经游玩的点(R中的点), 且终点是 i 的最小花费,s指的是状态 */ int dis[maxn][maxn]; int rs[maxn]; int dp[1<<15+2][20]; int n,m,r; int main(){ memset(dis,inf,sizeof(dis)); memset(dp,inf,sizeof(dp)); cin>>n>>m>>r; for(int i=0;i<r;i++){ cin>>rs[i]; } int x,y,w; for(int i=1;i<=m;i++){ cin>>x>>y>>w; dis[x][y]=dis[y][x]=w; } for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j||j==k||i==k){ continue; } dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } } } memset(dp,inf,sizeof(dp)); for(int i=0;i<r;i++){ dp[1<<i][i]=0; } for(int s=1;s<(1<<r);s++){ for(int i=0;i<r;i++){ if(!(s>>i)&1) continue; int x=rs[i]; for(int j=0;j<r;j++){ if((s>>j)&1){ continue; } int y=rs[j]; dp[s|(1<<j)][j]=min(dp[s|(1<<j)][j],dp[s][i]+dis[x][y]); } } } int ans=inf; for(int i=0;i<r;i++){ ans=min(ans,dp[(1<<r)-1][i]); } cout<<ans<<endl; }
标签:郊区,铁子,int,状压,rs,花费,春游,dp 来源: https://www.cnblogs.com/lipu123/p/14394094.html