洛谷题目传送门

很可惜,充满Mo力的Mo拟退火并不是正解。不过这是一道最适合开始入手Mo拟退火的好题。

对模拟退火还不是很清楚的可以看一下

这道题还真和能量有点关系。达到平衡稳态的时候,物体的总能量应该是最小的。而总的能量来源于每个物体的重力势能之和。要想让某个物体势能减小,那就让拉着它的绳子在桌面下方的长度尽可能的长,也就是桌面上的要尽可能短。由此看来,某个物体的势能与桌面上的绳子的长度、物体重量都成正比。

于是,为了找到平衡点,我们要找一个点使得\(\sum_{i=1}^n d_i*w_i\)最小(\(d_i\)为\(i\)点到该点的距离)。

函数已经求出来了,接下来就是正常的模拟退火过程。注意一些细节就好了。

首先,初始解可以设成\(({\sum_{i=1}^n x_i\over n},{\sum_{i=1}^n y_i\over n})\),可以更接近正解

解变动值最好随机两个值,\(\Delta x\)和\(\Delta y\)。随机变动距离和角度可能常数有点大。

然后是写法问题。蒟蒻又学习了一招,知道有一个常数叫RAND_MAX,用于生成\([0,1)\)的随机值还是很方便的,在不同机子下可移植性也很强。(难怪Windows上rand出来的都是短整形数)

另外,因为退火的时候有可能本来找到了最优解,但后来接受了较劣解并逐步降温稳定了,那么也就是说本来找到的最优解到最后却给弄丢了。

为了避免这种情况,蒟蒻参考YL的做法,设一个全局最优解best,它只接受比自己更优的解。

而且这样还有一个好处,就是进行多次退火的过程中,也能保证best是单调递减的,无论如何也不会变劣。

最后就是调参数的问题了。

发现自己写了个假的模拟退火以后,蒟蒻马上一改,却发现参数又需要重新调。。。。。。(YL据老也背了锅)

拼命的二分,二分。。。。。。参数大得都要TLE了还是不能保证正确率?!

结果小号提交记录第二次刷屏了(第一次还是打表过洛谷愚人节T3。。。。。。)

后来突然猛地一想:\(n,x,y,w\)都不小,乘来乘去不会掉精度了吧?

于是改用long double继续,情况好多了

update:

可能发现在哪里咕咕了,应该不是\(n,x,y,w\)的问题。

随机变动距离写的是T*(rand()*2-RAND_MAX),也就意味着生成了一个\([-T*RAND\_MAX,T*RAND\_MAX)\)的数。

这没有错,因为RD的值域确实与T成正比,但不对劲的是它太大了,难道是因为这里爆double精度?

可是看到其它巨佬用double没出锅诶。。。

其实还有一个优化就是,退火结束后从best处向小范围内rand一些点,rand个千把次,找最优的一个点作为答案。

这样比多次退火效率高了不少,就更容易弥补之前没找到最优解的遗憾了。

听XZY大佬的讲课学的,stO XZY Orz

代码蒟蒻就懒得重写了。。。。。。(连个理由都懒得找)

下面的参数可供参考,因为D算是很小的了,所以跑得快多了,只要28ms

#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstdlib>
#define RG register
#define R RG long double
#define RD T*(rand()*2-RAND_MAX)//生成一个[-T*RAND_MAX,T*RAND_MAX)的随机变动距离
//以前写的是T*((double)rand()/RAND_MAX*2-1),总是WA(可能是先除后乘掉精度了),然后就参考了YL的写法
const int N=1009;
const long double D=0.97,EPS=1e-14;//更新后二分出了保证极高正确率和较高效率的参数
double x[N],y[N],w[N];
int n;
inline long double calc(R x0,R y0){
R res=0,dx,dy;
for(RG int i=1;i<=n;++i){//函数求值
dx=x[i]-x0;dy=y[i]-y0;
res+=sqrt(dx*dx+dy*dy)*w[i];
}
return res;
}
int main(){
R T,x0,y0,x1,y1,res,ans,best,bx=0,by=0;
RG int i,times=1;//一次的正确率很高的,不放心也可以调大
scanf("%d",&n);
for(i=1;i<=n;++i){
scanf("%lf%lf%lf",&x[i],&y[i],&w[i]);
bx+=x[i];by+=y[i];
}//初始横纵坐标均选择平均值
best=ans=calc(bx/=n,by/=n);
srand(time(NULL));
while(times--/*clock()<CLOCKS_PER_SEC*0.9*/){//比赛的时候试试注释里写的,卡时还是靠谱些
ans=best;x0=bx;y0=by;
for(T=100000;T>EPS;T*=D){
x1=x0+RD;y1=y0+RD;
res=calc(x1,y1);
if(best>res)
best=res,bx=x1,by=y1;//更新最优答案
if(ans>res||exp((ans-res)/T)>(long double)rand()/RAND_MAX)
ans=res,x0=x1,y0=y1;//接受新解
}
};
printf("%.3Lf %.3Lf\n",bx,by);
return 0;
}

洛谷P1337 【[JSOI2004]平衡点 / 吊打XXX】(模拟退火)的更多相关文章

  1. 洛谷P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)

    题目描述 如图:有n个重物,每个重物系在一条足够长的绳子上.每条绳子自上而下穿过桌面上的洞,然后系在一起.图中X处就是公共的绳结.假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到 ...

  2. 洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX

    洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX 点击进入FakeHu的模拟退火博客 神仙模拟退火...去看fakehu的博客吧...懒得写了... 因为精度问题要在求得的最优解附近(大约 ...

  3. 洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX 解题报告

    P1337 [JSOI2004]平衡点 / 吊打XXX 题目描述 有 \(n\) 个重物,每个重物系在一条足够长的绳子上.每条绳子自上而下穿过桌面上的洞,然后系在一起.\(X\)处就是公共的绳结.假设 ...

  4. [洛谷P1337][JSOI2004]平衡点 / 吊打XXX

    题目大意:有$n$个重物,每个重物系在一条绳子上.所有绳子系在一起,问绳结最终平衡于何处. 题解:$NOIP$前学学模拟退火,但发现我脸好黑啊... 卡点:脸黑 C++ Code: #include ...

  5. 洛谷P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)

    传送门 先坑着,联赛活着回来的话我就写(意思就是我绝对不会写了) //minamoto #include<cstdio> #include<cmath> #include< ...

  6. P1337 [JSOI2004]平衡点 / 吊打XXX 模拟退火

    链接 https://www.luogu.org/problemnew/show/P1337 思路 交了好多发,都是wrong 初始值取平均数就1A了 真的是玄学的算法 代码 // luogu-jud ...

  7. LUOGU P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)

    传送门 解题思路 学习了一下玄学算法--模拟退火,首先要求平衡处,也就是求势能最小的地方,就是求这个点到所有点的距离*重量最小.剩下的几乎是模拟退火的板子了. #include<iostream ...

  8. luogu1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)

    推荐博客:模拟退火总结(模拟退火)by FlashHu.模拟退火的原理,差不多就是不断地由现有的值不断地试探,不断地转到更优的值,并在一定概率下转到较差的值. 题目传送门:luogu1337 [JSO ...

  9. P1337 [JSOI2004]平衡点 / 吊打XXX

    题目描述 如图:有n个重物,每个重物系在一条足够长的绳子上.每条绳子自上而下穿过桌面上的洞,然后系在一起.图中X处就是公共的绳结.假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到 ...

  10. Luogu P1337 [JSOI2004]平衡点 / 吊打XXX

    一道入门模拟退火的经典题,还是很考验RP的 首先我们发现神TM这道题又和物理扯上了关系,其实是一道求广义费马点的题目 首先我们可以根据物理知识得到,当系统处于平衡状态时,系统的总能量最小 又此时系统的 ...

随机推荐

  1. linux:NFS

    1.简介 2.安装 安装分为服务端和客户端 [1]我们先拿一台机做服务端 yum install nfs-utils rpcbind -y 然后我们查查看安装没有,查询一个包是否被安装# rpm -q ...

  2. 【转载】Qt中图像的显示与基本操作

    Qt可显示基本的图像类型,利用QImage.QPxmap类可以实现图像的显示,并且利用类中的方法可以实现图像的基本操作(缩放.旋转). 参考:Qt中图像的显示与基本操作 - ykm0722的专栏 - ...

  3. SpringBoot + Security实现权限控制

    网上找了好几个,因为各种原因不太行,下面这个亲测可行 参考:https://blog.csdn.net/u012702547/article/details/54319508 基于SpringBoot ...

  4. node(2) EventEmitter类 事件队列 事件和error事件方法

    事件队列的核心:事件触发与事件监听器功能的封装. // 引入 events 模块 var events = require('events'); // 创建 eventEmitter 对象 var e ...

  5. jq demo--横向+展开菜单,支持m站

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. 第三节 java 数组

    一维数组: 同一种类型数据的集合,其实数组就是一个容器. 好处: 可以自动给数组中的元素从0开始编号,方便操作这些元素. 格式1: 元素类型[]  数组名 = new 元素类型 [元素个数或者元素长度 ...

  7. static全局变量与普通全局变量的区别,static局部变量与普通局部变量的区别,static函数与普通函数的区别

    static全局变量与普通全局变量的区别 static全局变量和普通全局变量的存储方式没有不同,如果它们都已经初始化,那么存放在进程的数据段中,否则存放在bss段.这两者的不同点在于作用域不同,当一个 ...

  8. DevExpress WinForms v18.2新版亮点(二)

    行业领先的.NET界面控件2018年第二次重大更新——DevExpress v18.2日前正式发布,本站将以连载的形式为大家介绍各版本新增内容.本文将介绍了DevExpress WinForms v1 ...

  9. 从今天开始 每天记录HTML,CSS 部分的学习笔记

    从今天开始 每天记录HTML,CSS 部分的学习笔记

  10. mybatis 插入空值时报错 TypeException

    报错内容:nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ...