1. 程式人生 > 實用技巧 >NOIP2017 寶藏

NOIP2017 寶藏

樹上的旅行商問題

#include<bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define N 15
using namespace std;
int dist[N][N],dis[N],flag[N][N],dp[1<<13],n,m;
inline int read()
{
    int f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
    return x;
}
void dfs(int x)
{
    for(int i=1;i<=n;i++)
        if((1<<(i-1))&x) //i在我們所走過的點的集合中 
            for(int j=1;j<=n;j++) //j不在我們走過的集合中 
                if(!(1<<(j-1)&x)&&flag[i][j]) //並且i可以走到j 
                    if(dp[1<<(j-1)|x]>dp[x]+dis[i]*dist[i][j])
                	{
                        int t=dis[j];
                        dis[j]=dis[i]+1;
                        dp[1<<(j-1)|x]=dp[x]+dis[i]*dist[i][j];
                        dfs(1<<(j-1)|x);
                        dis[j]=t;
                    }
}
int main()
{
	n=read(),m=read();
	int ans=inf;
	memset(dist,0x3f,sizeof(dist));
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read(),z=read();
		flag[x][y]=1;
		flag[y][x]=1;
		dist[x][y]=min(dist[x][y],z);
		dist[y][x]=min(dist[y][x],z);
	}
	for(int i=1;i<=n;i++) //列舉下最開始的點是哪一個 
	{
		memset(dis,0x3f,sizeof(dis));
		memset(dp,0x3f,sizeof(dp));
		dis[i]=1;
		dp[1<<(i-1)]=0;
		dfs(1<<(i-1));
		ans=min(ans,dp[(1<<n)-1]);
	}
	printf("%d",ans);
	return 0;
}