• 【洛谷P3959】宝藏


    题目

    题目链接:https://www.luogu.com.cn/problem/P3959
    参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 (n) 个深埋在地下的宝藏屋, 也给出了这 (n) 个宝藏屋之间可供开发的$ m$ 条道路和它们的长度。

    小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多。

    小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定。

    在此基础上,小明还需要考虑如何开凿宝藏屋之间的道路。已经开凿出的道路可以 任意通行不消耗代价。每开凿出一条新道路,小明就会与考古队一起挖掘出由该条道路 所能到达的宝藏屋的宝藏。另外,小明不想开发无用道路,即两个已经被挖掘过的宝藏 屋之间的道路无需再开发。

    新开发一条道路的代价是:

    [mathrm{L} imes mathrm{K} ]

    L代表这条道路的长度,K代表从赞助商帮你打通的宝藏屋到这条道路起点的宝藏屋所经过的 宝藏屋的数量(包括赞助商帮你打通的宝藏屋和这条道路起点的宝藏屋) 。

    请你编写程序为小明选定由赞助商打通的宝藏屋和之后开凿的道路,使得工程总代 价最小,并输出这个最小值。

    思路

    (n) 特别小,有效的边数 (m) 也不超过 (70),要求最优解。
    直接上模拟退火,每次在当前最优的序列上随机两个位置交换,(O(n^2)) 贪心求路径长度,再降温即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=15,M=70;
    const double delta=0.996;
    int n,m,tot,head[N],a[N],dep[N],dis[N][N];
    ll ans;
    
    ll work()
    {
    	memset(dep,0x3f3f3f3f,sizeof(dep));
    	dep[a[1]]=0;
    	ll sum=0;
    	for (int i=2;i<=n;i++)
    	{
    		ll mind=100000000000000000,pos;
    		for (int j=1;j<=n;j++)
    			if (1LL*(dep[j]+1)*dis[a[i]][j]<mind)
    				mind=1LL*(dep[j]+1)*dis[a[i]][j],pos=j;
    		sum+=mind; dep[a[i]]=dep[pos]+1;
    	}
    	return sum;
    }
    
    void solve()
    {
    	srand(rand());
    	double t0=8000,t1=1e-14;
    	while (t0>t1)
    	{
    		int x=rand()%n+1,y=rand()%n+1;
    		swap(a[x],a[y]);
    		ll sum=work();
    		if (sum<ans) ans=sum;
    		else if (exp(sum-ans)<1.0*rand()/RAND_MAX) swap(a[x],a[y]);
    		t0*=delta;
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	memset(dis,0x3f3f3f3f,sizeof(dis));
    	scanf("%d%d",&n,&m);
    	srand(114514+19260817);
    	for (int i=1,x,y,z;i<=m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		dis[x][y]=dis[y][x]=min(dis[x][y],z);
    	}
    	for (int i=1;i<=n;i++) a[i]=i;
    	random_shuffle(a+1,a+1+n);
    	ans=1000000000000000;
    	solve(); solve(); solve();
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    [ES6]react中使用es6语法
    [前端自动化]grunt的简单使用
    [react-native]react-native填坑笔记
    [CSS布局]简单的CSS三列布局
    简单说下cookie,LocalStorage与SessionStorage.md
    [算法学习]开始leetcode之旅
    monorepo和multrepo的简介
    异步请求(ajax,http) 之 逐渐完善的大全
    Java中Synchronized的用法
    Node.js小白开路(一)-- fs篇
  • 原文地址:https://www.cnblogs.com/stoorz/p/13845035.html
Copyright © 2020-2023  润新知