我对模拟退火的理解:https://www.cnblogs.com/AKMer/p/9580982.html

我对爬山的理解:https://www.cnblogs.com/AKMer/p/9555215.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3680

模拟退火在计算几何方面有很大的用处,特别是求费马点一类的问题。

作为一个文化课很渣的人我就没办法详细地告诉你这道题怎么从物理题转移成信息学题目了。但是灵性的理解一下,题目意思就是要你找平面上的广义费马点。

所谓费马点,就是在一个\(n\)边形内,这个点如果到\(n\)个顶点距离和最小,那么它就是这个\(n\)边形的费马点。

然后广义费马点就是顶点上带权的费马点,统计的时候距离要乘上这个权值再加起来。

我们灵性的脑补一波就可以发现,这个题目显然不存在局部最优解,所以我们可以大胆爬山。

然后我们再灵性的想一想:首先我们可以把初始点定在\(n\)个点的中心位置,这样可以减少转移次数。再者,一个绳结如果不在最终目标点的话,那么它肯定有往最终目标点移动的趋势。所以我们在温度很高的时候,绳结坐标的跳动距离就设置大一点,就先向趋势所在的方向跳。慢慢的温度低了,我们就跳小一点的步子,慢慢稳定下来,这样子最后甚至可以准确的命中正确答案!

然后因为这个性质,爬山算法就比模拟退火在这道题上优秀得多了。爬山算法可以直接在\(BZOJ\)上\(AC\),但是模拟退火不行。

毕竟没有局部最优解你还接受更加差的状态就显得很智障了……

时间复杂度:\(O(能A)\)

空间复杂度:\(O(能A)\)

爬山算法\(AC\)代码如下:

#include <cmath>
#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std; #define sqr(a) ((a)*(a)) const int maxn=1e4+5; int n;
double ansx,ansy,ans=1e18;//ans记录最小权值,ansx记录历史最优节点的x,ansy记录历史最优节点的y struct gty {
double x,y,w;//x,y存坐标,w存重量
}point[maxn]; double len() {
double x=rand()%200000-100000;
return x/100000;
}//随机一个-100000~100000之间的长度 double dis(double x1,double y1,double x2,double y2) {
return sqrt(sqr(x1-x2)+sqr(y1-y2));
}//求(x1,y1),(x2,y2)两点之间的距离 double calc(double x,double y) {//计算以点(x,y)为绳结时候的权值
double tmp=0;
for(int i=1;i<=n;i++)
tmp+=dis(x,y,point[i].x,point[i].y)*point[i].w;//直接暴力算
if(tmp<ans) {ans=tmp;ansx=x,ansy=y;}//如果权值比历史最优更小,那么就更新历史最优
return tmp;//返回权值
} int main() {
srand(time(0));
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].w);
ansx+=point[i].x;ansy+=point[i].y;
}ansx/=n;ansy/=n;double now_x=ansx,now_y=ansy;//读入以及初始化
for(double T=10000;T>=1e-5;T*=0.98) {//爬山使用退火的降温机制似乎可以更灵性!
double nxt_x=now_x+len()*T,nxt_y=now_y+len()*T;//爬山,每次跳len*T那么长,那么随着温度慢慢降低也会趋向稳定
if(calc(now_x,now_y)>calc(nxt_x,nxt_y))
now_x=nxt_x,now_y=nxt_y;//如果这个方向是绳结移动的趋势方向那么就直接跳过去
}
printf("%.3lf %.3lf\n",ansx,ansy);//输出
return 0;
}

模拟退火不能\(AC\)代码如下:

#include <cmath>
#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std; #define sqr(a) ((a)*(a)) const int maxn=1e4+5;
const double T_0=1e-5;
const double del_T=0.98; int n;
double ansx,ansy,ans=1e18; struct gty {
double x,y,w;
}point[maxn]; double dis(double x1,double y1,double x2,double y2) {
return sqrt(sqr(x1-x2)+sqr(y1-y2));
} double calc(double x,double y) {
double tmp=0;
for(int i=1;i<=n;i++)
tmp+=dis(x,y,point[i].x,point[i].y)*point[i].w;
if(tmp<ans) {ans=tmp;ansx=x,ansy=y;}
return tmp;
} double len() {
double x=rand()%200000-100000;
return x/100000;
} void Anneal() {
double T=1e4,now_x=ansx,now_y=ansy;
while(T>=T_0) {
double nxt_x=now_x+len()*T;
double nxt_y=now_y+len()*T;
double tmp1=calc(now_x,now_y);
double tmp2=calc(nxt_x,nxt_y);
if(tmp2<tmp1||exp((tmp1-tmp2)/T)*RAND_MAX>rand())//除了这里和爬山算法是一模一样的。这里加了一个模拟退火特有的“接受不优于当前状态的状态”的概率
now_x=nxt_x,now_y=nxt_y;
T*=del_T;
}
} int main() {
srand(time(0));
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].w);
ansx+=point[i].x,ansy+=point[i].y;
}ansx/=n,ansy/=n;
for(int i=1;i<=54;i++)Anneal();
printf("%.3lf %.3lf\n",ansx,ansy);
return 0;
}

BZOJ3680:吊打XXX的更多相关文章

  1. [JSOI2004]平衡点/[BZOJ3680]吊打XXX

    [JSOI2004]平衡点/[BZOJ3680]吊打XXX 题目大意: 有\(n(n\le10000)\)个重物,每个重物系在一条足够长的绳子上.每条绳子自上而下穿过桌面上的洞,然后系在一起.假设绳子 ...

  2. BZOJ3680 吊打XXX 【模拟退火】

    Description gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty.gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了.蒟蒻们将n个gty吊在n根绳子上,每根绳子穿过天台的一个洞 ...

  3. BZOJ3680:吊打XXX(模拟退火)

    Description gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty.gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了.蒟蒻们将 n个gty吊在n根绳子上,每根绳子穿过天台的一个 ...

  4. BZOJ3680 : 吊打XXX

    本题就是找一个受力平衡的点 我们一开始假设这个点是(0,0) 然后求出它受到的力,将合力正交分解后朝着合力的方向走若干步,并不断缩小步长,一步步逼近答案 #include<cstdio> ...

  5. bzoj3680: 吊打XXX(模拟退火)

    题目要求 最小(dis表示绳结到点i的距离),就是个广义费马点的题,模拟退火裸题QAQ 模拟退火就是优化后的爬山算法,一开始先随机一个平均点,接下来如果随机到的点比当前点劣,温度比较高的话也有几率跳过 ...

  6. 【BZOJ3680】吊打XXX(模拟退火)

    [BZOJ3680]吊打XXX(模拟退火) 题面 BZOJ 题解 模拟退火... 就是模拟退火 然后这题有毒 各种调参数之后终于\(AC\)了.. 这种题就是玄学呀... 温度要调大 最后跑完还要向四 ...

  7. 模拟退火小结(Bzoj3680:吊打xxx)

    简介 就是模拟退火的物理过程,每次随机逼近乘上温度,以\(e^{\Delta/T}\)的概率接受答案,随机一个概率比较 然后就是调参+乱搞 题目 Bzoj3680:吊打xxx 代码 # include ...

  8. 模拟退火法(吊打XXX)Bzoj3680

    3680: 吊打XXX Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 308  Solved: 94 [Subm ...

  9. 【BZOJ3680】吊打xxx [模拟退火]

    吊打XXX Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description gty又虐了一场比赛,被虐的蒟蒻 ...

  10. [bzoj3680]吊打XXX_模拟退火

    吊打XXX bzoj-3680 题目大意:在平面上给定n个点,每个点有一个权值.请在平面上找出一个点(不一定在这n个点内找)使得这个点到n个点的距离*权值最小,即求这n个点的重心. 注释:$1\le ...

随机推荐

  1. ls --color=xxx

      默认的ls是由"ls --color=auto"组成的,假如某个目录中的文件特别多,我不希望显示颜色(可以加快显示),那就需要指定单独的参数. [root@localhost ...

  2. 关于Future

    1 为什么需要Callable和Future Runnable没有返回值,也不抛异常,这样主线程不能知道子线程的执行结果. 为了解决这个问题就有了Callable和Future.Callable提供的 ...

  3. 【python】-- 内置函数、软件目录开发规范(代码编码风格)

    内置函数 一.内置函数表格 二.内置函数演示 1.abs(x) 功能:取数的绝对值 >>> abs(-1) #取-1的绝对值 1 ########################## ...

  4. Python菜鸟之路:前端HTML基础

    前面的章节中,Python的基本知识已经差不多介绍完了.本节介绍HTML相关的知识.需要着重声明的是,前端知识是非常非常重要的知识,以我实际项目经验来看,一个项目的瓶颈在设计和前端.设计就先不说了,前 ...

  5. hibernate 多对多操作(级联操作)

    一.级联保存 分别在用户和角色配置文件中在set标签中加入cascade="save-update": 示例:添加同时添加用户对象和角色对象并关联两个对象: 只需将角色放入用户对象 ...

  6. Linux安装过程记录信息

    全新的linux安装完成后,会在root目录下有一下三个文件,记录了Linux的安装细节 anaconda-ks.cfg 以Kickstart配置文件的格式记录安装过程中设置的选项信息 install ...

  7. openstack 官方镜像qcow2 下载和修改密码

    下载地址: CentOS6:http://cloud.centos.org/centos/6/images/ CentOS7:http://cloud.centos.org/centos/7/imag ...

  8. require.js vs browserify

    require.js vs browserify require.js是模块加载器:browserify是预编译工具 require.js遵循的是AMD规范:browserify遵循的是CommonJ ...

  9. xcode6

    官方的xcode6下载太慢,这里送上百度网盘地址: http://pan.baidu.com/s/1hqze1hi

  10. POJ - 3414 Pots 【BFS】

    题目链接 http://poj.org/problem?id=3414 题意 给出两个杯子 容量分别为 A B 然后给出C 是目标容量 有三种操作 1 将一个杯子装满 2.将一个杯子全都倒掉 3.将一 ...