题目链接
2 1 1 2 100 3 2 1 2 40 2 3 50 3 3 1 2 3 1 3 4 2 3 10
100 90 7
#include<string.h> #include<stdio.h> #include<algorithm> #define inf 1e12 #define ll long long using namespace std; ll n,m; ll a[15][15]; ll c[15];///存的是3的0次方到10次方的值 ll state[600000][15];///存的是n次方以内的所有状态,将这些状态保存在第二维中 ll dp[600000][15]; void init() { c[0]=1; for(ll i=1;i<=n;i++) c[i]=c[i-1]*3; for(ll i=0;i<c[n];i++)///预处理每一个状态包含的0 1 2的情况,共n位,因为需要n位 { ll j=0,x=i; while(j<n) { state[i][j]=x%3; x/=3; j++; } } for(ll i=0;i<n;i++) for(ll j=0;j<n;j++) a[i][j]=inf; for(ll i=0;i<c[n];i++) for(ll j=0;j<n;j++) dp[i][j]=inf; for(ll i=0;i<n;i++) dp[c[i]][i]=0;///因为是从任意点开始都行,所以在初始化时要把从第0个点,第1个点......第n-1各点都初始化为0,如果是必须从第0各点开始,则只需要使dp[1][0]=0即可 } int main() { while(scanf("%lld%lld",&n,&m)!=EOF) { init(); for(ll i=1;i<=m;i++) { ll x,y,cc; scanf("%lld%lld%lld",&x,&y,&cc); x--,y--; a[x][y]=a[y][x]=min(a[x][y],cc);///防止有重边 } ll ans=inf; for(ll i=0;i<c[n];i++) { ll flog=1; for(ll j=0;j<n;j++) { if(!state[i][j]) flog=0; for(ll k=0;k<n;k++) { if(state[i][k]>=2||k==j||a[j][k]==inf) continue;///此时想从j到k,那么k这个状态必须是2以下,要不然不能去 dp[i+c[k]][k]=min(dp[i+c[k]][k],dp[i][j]+a[j][k]); } } if(flog)///flog为1代表所有城市都至少去了一次,因此答案ans可以更新 { for(ll j=0;j<n;j++) ans=min(ans,dp[i][j]); } } if(ans==inf) puts("-1"); else printf("%lld\n",ans); } return 0; }