【NOIP 2017】宝藏(状压dp)

用dp[i]来表示状态i下的最优方案,dis[j]表示j到根节点的距离(题目中所描述的K)用dfs来更新答案

#include<bits/stdc++.h>
#include<cstdio>
#define INF 2139062143
#define N 12
#define M 1005
using namespace std;
int g[N][N],n,m,dis[N],f[(1<<N)+10];
inline void update(int x,int y,int z)
{
	g[x][y]=z;
	g[y][x]=z;
}	
void dfs(int s)
{
	for(int i=1;i<=n;i++)
	{
		if((1<<(i-1))&s)
		{
			for(int j=1;j<=n;j++)
			{
				if(g[i][j]!=INF&&!((1<<(j-1))&s))
				{
					if(f[1<<(j-1)|s]>f[s]+dis[i]*g[i][j])
					{
						dis[j]=dis[i]+1;
						f[1<<(j-1)|s]=f[s]+dis[i]*g[i][j];
						dfs(1<<(j-1)|s);	
						dis[j]-=1;
					}
				}
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);cout.tie(NULL);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			g[i][j]=INF;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		if(z<g[x][y])	update(x,y,z);
	}
	int ans=INF;
	for(int i=1;i<=n;i++)	//枚举起点
	{
		memset(dis,127,sizeof(dis));
		memset(f,127,sizeof(f));
		dis[i]=1;
		f[1<<(i-1)]=0;
		dfs(1<<(i-1));
		ans=min(ans,f[(1<<n)-1]);
	} 
	cout<<ans<<endl;
	return 0;
}
posted @ 2018-10-17 13:07  Patrickpwq  阅读(65)  评论(0编辑  收藏  举报