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

题干:

题目描述

参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 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. html5——渐变

    线性渐变 <style> div { width: 700px; height: 100px; /*方向:从右向左*/ /*起始颜色:黄色*/ /*终止颜色:绿色*/ background ...

  2. SQL Server建库-建表-建约束

    ----------------------------------------SQL Server建库-建表-建约束创建School数据库------------------------------ ...

  3. 10、scala面向对象编程之Trait

    1.  将trait作为接口使用 2.trait中定义具体方法 3.trait定义具体字段 4.trait中定义抽象字段 5.为实例对象混入trait 6.trait调用链 7.在trait中覆盖抽象 ...

  4. c++将bool变量以文字形式打印

    #include <iostream> // std::cout, std::boolalpha, std::noboolalpha int main () { bool b = true ...

  5. Linux 配置JDK + MyEclipse

    版本:Ubuntu16.04: jdK: Java SE Development Kit 8u102; My Eclipse: 10.6; JDK配置的细致步骤参见此处. 就一点要注意: 请使用代码进 ...

  6. Java程序员2016年终总结

    回顾2016年, 很庆幸,自己能在2016年年尾找到一份满意的web后台开发工作.这也是我学习编程以来第一份开发工作,我很是珍惜. 还记得大三接触了Java的JFrame编写的坦克大战之后,就对编程产 ...

  7. Dynamics 365 CRM Connected Field Service 自动发送command

    上期降到了怎样部署connected field service(CFS) 我们假设现在IoT 设备是温度监控器, 当温度触发我们之前预设的温度值, IoT会通过IoT Hub 发送IoT Alert ...

  8. cocos creator destroy方法

    node.destroy(),Node.destroyAllChildren并不会立即销毁,实际销毁操作会延迟到当前帧渲染前执行. 这段话可能不明白,但是在Node.destroyAllChildre ...

  9. POJ3984——迷宫问题

    迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 31616   Accepted: 18100 Descriptio ...

  10. ASP.NET误人子弟教程:在MVC下如何返回图片

    这几天忙着一些小事,也没有写什么了,今天,我们来玩一个比较简单的东东.就是在MVC下如何返回图片,相信,在传统WebForm下,大家都晓得怎么弄,方也不限于一种,但是,在架构较为严格的MVC里面,刚开 ...