NC16418. [NOIP2017]宝藏
描述
输入描述
第一行两个用空格分离的正整数 n 和 m,代表宝藏屋的个数和道路数。
接下来 m 行,每行三个用空格分离的正整数,分别是由一条道路连接的两个宝藏屋的编号(编号为 1~n),和这条道路的长度 v。
输出描述
输出共一行,一个正整数,表示最小的总代价。
示例1
输入:
4 5 1 2 1 1 3 3 1 4 1 2 3 4 3 4 1
输出:
4
说明:
示例2
输入:
4 5 1 2 1 1 3 3 1 4 1 2 3 4 3 4 2
输出:
5
说明:
C++11(clang++ 3.9) 解法, 执行用时: 204ms, 内存消耗: 8604K, 提交时间: 2019-10-31 17:05:49
#include<bits/stdc++.h> using namespace std; int dp[1<<12+9],dis[15],n,m,g[15][15]; void dfs(int s){ for(int i=1;i<=n;i++) if((1<<(i-1))&s) { for(int j=1;j<=n;j++) if(!((1<<(j-1))&s)&&g[i][j]){ if(dp[s|(1<<j-1)]>dp[s]+g[i][j]*dis[i]) { int t=dis[j]; dp[s|(1<<j-1)]=dp[s]+g[i][j]*dis[i]; dis[j]=dis[i]+1; dfs(s|(1<<j-1)); dis[j]=t; } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); if(!g[u][v]) g[u][v]=g[v][u]=w; else g[u][v]=g[v][u]=min(g[u][v],w); } int ans=1e9; for(int i=1;i<=n;i++) { memset(dp,0x3f,sizeof dp); dp[1<<(i-1)]=0; dis[i]=1; dfs(1<<(i-1)); ans=min(ans,dp[(1<<n)-1]); } printf("%d\n",ans); }