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

题干:

题目描述

参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 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. dotnetnuke 添加用户属性 Profile

    if (DotNetNuke.Entities.Profile.ProfileController.GetPropertyDefinitionByName(this.PortalId, "Q ...

  2. Forum/viewthread.php代码备份

    <!--{eval $lzthread = DB::fetch_all("SELECT `tid`,`subject` FROM ".DB::table('forum_thr ...

  3. php base64互转pdf

    /* * base64转pdf */ function base642pdf($formTxt,$toPdf) { $file = file_get_contents($formTxt);//读 $d ...

  4. windows设置右键菜单

    1. 打开注册表,(win + R,输入regedit) 2. 在 HKEY_CLASSES_ROOT\Directory\Background\shell 中,新建项:如(cmder),在 cmde ...

  5. Vue和JQuery相比,除了节省了开发成本,还有什么优点?

    1.模块化,变量都是私有作用域,JQuery只能用全局变量.闭包,影响性能 2.组件化 3.因为1,所以方便维护 vuex 要注意刷新清空的问题 vue-router是局部刷新,window.loca ...

  6. c++ map迭代器

    #include <stdio.h> #include <map> using namespace std; int main(){ map<int, int> m ...

  7. 使用Oracle函数在创建表的时候自动加入生成的流水号 生成格式是:前缀+年月日+00000

    CREATE OR REPLACE FUNCTION fn_no_make(v_type VARCHAR2, v_number_col VARCHAR2, v_table_name VARCHAR2) ...

  8. Secret of Chocolate Poles (Aizu1378——dp)

    Select Of Chocolate Poles 题意:有一个竖直放置的高度为l cm的盒子,现在有三种方块分别为1cm的白块,1cm的黑块,k cm的黑块,要求第一块放进去的必须是黑色的,盒子最上 ...

  9. 使用 Cordova 打包 app

    1.安装nodejs 2.安装 cordova npm install -g cordova 3.Cordova 打包成安卓APK需要用到ANT打包工具,首先配置好java环境: 下载安装Java J ...

  10. 1.1 Java程序设计平台

    Java并不只是一种语言.在此之前出现的那么多中语言也没有能够引起那么大的轰动.Java是一个完整的平台,有一个庞大的库,其中包含了很多可重用的代码和一个提供诸如安全性.跨操作系统的可移植性以及自动垃 ...