竟然模拟退火能做!我就直接抄代码了,我加了点注释。

题干:

题目描述

参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nn 个深埋在地下的宝藏屋, 也给出了这 nn 个宝藏屋之间可供开发的 mm 条道路和它们的长度。

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

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

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

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

$$\mathrm{L} \times \mathrm{K}$$

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

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

输入输出格式

输入格式:
第一行两个用空格分离的正整数 $n,m$,代表宝藏屋的个数和道路数。 接下来 $m$ 行,每行三个用空格分离的正整数,分别是由一条道路连接的两个宝藏 屋的编号(编号为 $-n$),和这条道路的长度 $v$。 输出格式:
一个正整数,表示最小的总代价。 输入输出样例 输入样例#: 复制 输出样例#: 复制 输入样例#: 复制 输出样例#: 复制 说明 【样例解释1】 小明选定让赞助商打通了$ $ 号宝藏屋。小明开发了道路 $ \to $,挖掘了 $$ 号宝 藏。开发了道路 $ \to $,挖掘了 $$ 号宝藏。还开发了道路 $ \to $,挖掘了$ $号宝 藏。工程总代价为:$ \times + \times + \times = $ 【样例解释2】 小明选定让赞助商打通了$ $ 号宝藏屋。小明开发了道路 $ \to $,挖掘了 $$ 号宝 藏。开发了道路 $ \to $,挖掘了 $$ 号宝藏。还开发了道路 $ \to $,挖掘了$ $号宝 藏。工程总代价为:$ \times + \times + \times = $ 【数据规模与约定】 对于$ \%$的数据: 保证输入是一棵树,$ \le n \le $,$v \le $ 且所有的 $v $都相等。 对于 $\%$的数据: $ \le n \le $,$ \le m \le $,$v \le $ 且所有的$ v $都相等。 对于$ \%$的数据: $ \le n \le $,$ \le m \le $,$v \le $ 对于$ \%$的数据: $ \le n \le $,$ \le m \le $,$v \le $

代码:

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring> #define inf 2147483647 using namespace std;
int n, m;
int map[][];
int depth[];
struct edge
{
int u, v;
};
bool operator < (struct edge a, struct edge b)
{
return depth[a.u]*map[a.u][a.v]>depth[b.u]*map[b.u][b.v];
}
int search(int source)
{
memset(depth, , sizeof(depth));
int vis[]= {};
priority_queue <struct edge> heap;
edge past[];
int p = ;
struct edge e, e2;
int cost = ;
depth[source]=;
vis[source]=;
for (int i = ; i <= n; ++i)
{
if (map[source][i] < inf)
{
e.u = source;
e.v = i;
heap.push(e);
}
}
for (int i = ; i < n; ++i)
{
e = heap.top();//每次取当前最优解
heap.pop();
while (!heap.empty() && ((vis[e.v] || rand() % (n) < ))) //注意这里的判断条件rand()%n<1,即对于一个当前最近点,不选择的几率随着n的增大而减小。
{
if (!vis[e.v]) past[p++] = e;
//对于跳过了的边,以后还用得上,等待选择结束后再压回优先队列中
e = heap.top();
heap.pop();
}
vis[e.v] = ;
depth[e.v] = depth[e.u]+;
if (p-->) //压回优先队列
{
for (; p>=; --p)
{
heap.push(past[p]);
}
}
p = ;
for (int i = ; i <= n; ++i)
{
if (map[e.v][i] < inf && !vis[i])
{
e2.u = e.v;
e2.v = i;
heap.push(e2);
}
}
cost += map[e.u][e.v] * depth[e.u];
}
return cost;
} int main()
{
int a, b, c;
scanf("%d %d", &n, &m);
for (int i = ; i <= n; ++i)
{
for (int j = ; j <= n; ++j)
{
map[i][j] = inf;
}
}
for (int i = ; i < m; ++i)
{
scanf("%d %d %d", &a, &b,&c);
map[a][b] = map[b][a] = min(c, map[a][b]);
}
srand();//瞎写的一个数,应该选什么数都差不多
int MIN = inf;
for (int j = ; j <; ++j)
{
//1000次运行是绝对万无一失的,事实上,400次就够了
for (int i = ; i <= n; ++i)
{
MIN = min(MIN, search(i)); //枚举起点
}
}
printf("%d", MIN);
return ;
}

P3959 宝藏 模拟退火。。。的更多相关文章

  1. 洛谷P3959 宝藏(模拟退火乱搞)

    题意 题目链接 题面好长啊...自己看吧.. Sol 自己想了一个退火的思路,没想到第一次交85,多退了几次就A了哈哈哈 首先把没用的边去掉,然后剩下的边从小到大排序 这样我们就得到了一个选边的序列, ...

  2. P3959 宝藏

    P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nn 个深埋在地下的宝藏屋, 也给出了这 nn 个宝藏屋之间可供开发的 mm 条道路和它们的长度. 小明决心亲自前往挖掘 ...

  3. 洛谷 P3959 宝藏 解题报告

    P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 \(n\) 个深埋在地下的宝藏屋, 也给出了这 \(n\) 个宝藏屋之间可供开发的 \(m\) 条道路和它们的长度. 小 ...

  4. [luogu]P3959 宝藏[NOIP][状态压缩DP]

    [luogu]P3959 宝藏[TREASURE] 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的 ...

  5. 【题解】P3959 宝藏 - 状压dp / dfs剪枝

    P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m  条道路和它们的长度. 小明决心亲自前往挖掘所有宝 ...

  6. [Luogu P3959] 宝藏 (状压DP+枚举子集)

    题面 传送门:https://www.luogu.org/problemnew/show/P3959 Solution 这道题的是一道很巧妙的状压DP题. 首先,看到数据范围,应该状压DP没错了. 根 ...

  7. P3959 宝藏 状压dp

    之前写了一份此题关于模拟退火的方法,现在来补充一下状压dp的方法. 其实直接在dfs中状压比较好想,而且实现也很简单,但是网上有人说这种方法是错的...并不知道哪错了,但是就不写了,找了一个正解. 正 ...

  8. Luogu P3959 宝藏

    这道题正解是状压DP,不过我不会所以写一下随机化算法来骗骗分. 听说当时考场上就有很多写prim然后挂掉的神仙,其实这道题是可以prim过的 prim是一种基于贪心的算法,在本题中由于盲目的选择当前最 ...

  9. 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)

    洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ...

随机推荐

  1. Showplan 逻辑运算符和物理运算符参考

    本文档已存档,并且将不进行维护. 运算符说明了 SQL Server 如何执行查询或数据操作语言 (DML) 语句. 查询优化器使用运算符生成查询计划,以创建在查询中指定的结果或执行在 DML 语句中 ...

  2. JS——i++与++i

    先赋值后自增: var i = 0; var n1 = i++; alert(i);//返回1 alert(n1);//返回0 先自增后赋值: var i = 0; var n1 = ++i; ale ...

  3. SQL基本操作——日期函数

    SQL日期:当我们处理日期时,最难的任务恐怕是确保所插入的日期的格式,与数据库中日期列的格式相匹配.只要数据包含的只是日期部分,运行查询就不会出问题.但是,如果涉及时间,情况就有点复杂了.在讨论日期查 ...

  4. C# Winform 获得下拉框 选中的值

    string PrintName = cmbPrinter.SelectedIndex.ToString(); PrintName = cmbPrinter.SelectedItem.ToString ...

  5. Python 之web动态服务器

    webServer.py代码如下: import socket import sys from multiprocessing import Process class WSGIServer(obje ...

  6. DECLARE_MESSAGE_MAP( )

    DECLARE_MESSAGE_MAP( ) 说明: 你的程序中的每一个CCmdTarget的派生类都可以提供一个消息映射以处理消息.在你的类声明的末尾使用DECLARE_MESSAGE_MAP宏.然 ...

  7. python SQLALchemy连接数据库。

    一.ORM与SQLALchemy简介 ORM 全程object Relational Mapping,对象关系映射.简单的说,ORM将数据库中的表与面向对象中的类建立了一种对应关系.这样在操作数据库时 ...

  8. 谷歌通过ajax获取本地JSON文件,为什么会提示跨域?

    在本地写了一段JSON代码,然后用ajax读取后,在浏览器打开,发现谷歌提示涉及到跨域问题, 但是跨域是由于协议,域名,端口中有一个不同,才会跨域,我在本地访问自己的文件,怎么和跨域扯上关系了?? 下 ...

  9. C++入职学习篇--代码规范(持续更新)

    C++入职学习篇--代码规范(持续更新) 一.头文件规范 在头文件中大家一般会定义宏.引入库函数.声明.定义全局变量等,在设计时最后进行分类,代码示范(自己瞎琢磨的,请多多指点): #ifndef T ...

  10. POJ 3984 迷宫问题 (BFS + Stack)

    链接 : Here! 思路 : BFS一下, 然后记录下每个孩子的父亲用于找到一条路径, 因为寻找这条路径只能从后向前找, 这符合栈的特点, 因此在输出路径的时候先把目标节点压入栈中, 然后不断的向前 ...