【解题报告】洛谷P3959 宝藏

发布时间:2022-07-04 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了【解题报告】洛谷P3959 宝藏脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

【解题报告】洛谷P3959 宝藏

原题连接

https://www.luogu.COM.cn/PRoblem/P3959

思路

这道题目,本来今天yht老师讲了个大力搜索,什么模拟退火来着,但是最后,还是回归了本,状态动态规划

首先我们这么想

我们每条路肯定只联通一次,然后我们对于可以钦定一个集合S

用来表示某个点选不选的最小代价

但我们要进行状态转移,我们要从一个点走到另一个点,然后要用某个节点的深度来计算代价

所以我们设置(f[x][S][d])来表示点x在S中并且深度为d的时候的最小代价

因为是从上一个状态走下来的,所以我们要加上这条边

则状态转移方程为

[f[x][1<<(x-1)|S][d]=min{sum+dis[y]+g[y][x]} ]

其中y和x表示上次的点和这次的点,sum表示这次以前的最小代价

dis数组在DFs的时候顺便处理一下就好了

代码

#include <iostream>
#include <cstdio>
#include <algorIThm>
#include <cstring>
#include <string>
#define int long long
using namespace std;
const int maxn=15;
const int INF=1e9;
int n,m,maxx;
int g[maxn][maxn];
int dis[maxn],ans=INF;
int f[maxn][1<<;maxn][maxn];
inline void dfs(int s,int sum,int dep)
{
	if(sum>=ans)
	return ;
	if(s==maxx)
	{
		ans=sum;
		return ;
	}
	for(int i=1;i<=n;i++)
	{
		if(!(1<<(i-1)&amp;s))
		continue;
		for(int j=1;j<=n;j++)
		{
			if(!(1<<(j-1)&s)&&g[i][j]<INF)
			{
				if(f[j][1<<(j-1)|s][dep+1]<=sum+dis[i]*g[i][j])
				continue;
				f[j][1<<(j-1)|s][dep+1]=sum+dis[i]*g[i][j];
				dis[j]=dis[i]+1;
				dfs(1<<(j-1)|s,f[j][1<<(j-1)|s][dep+1],dep+1);
			}
		}
	}
}
signed main()
{
	cin>>n>>m;
	maxx=(1<<n)-1;
	memset(g,0x3f3f3f,sizeof(g));
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		g[x][y]=g[y][x]=min(g[x][y],z);
	}
	for(int i=1;i<=n;i++)
	{
		memset(dis,0,sizeof(dis));
		memset(f,0x3f3f3f,sizeof(f));
		dis[i]=1;
		dfs(1<<(i-1),0,0);
	}
	cout<<ans<<'n';
	return 0;
}

脚本宝典总结

以上是脚本宝典为你收集整理的【解题报告】洛谷P3959 宝藏全部内容,希望文章能够帮你解决【解题报告】洛谷P3959 宝藏所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。