我对模拟退火的理解: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. EasyDSS+EasyNVR实现幼儿园直播/工地直播等分权限观看直播视频的功能

    在EasyNVR互联网直播服务器使用说明书中有关于EasyNVR分组的介绍: "EasyNVR的功能定位就是为视频应用层输出视频设备接入/标准视频输出的能力平台层,只做基础的视频通道接入.视 ...

  2. .net EF监控 MiniProfiler

    1.从NuGet上下载所需要的包:MiniProfiler.mvc,MiniProfiler,MiniProfiler.ef 2.Global.asax 加入 protected void Appli ...

  3. zoj 3356 Football Gambling II【枚举+精度问题】

    题目: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3356 http://acm.hust.edu.cn/vjudge/ ...

  4. git reset和git revert

    1 git reset commit-id 直接回到某次提交,该次commit-id之后的提交都会被删除. --hard,将index和本地都恢复到指定的commit版本. 2 git revert ...

  5. iOS基础动画的KeyPath取值

    一 .基础动画 1.基础动画的属性详解 注:Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程. 属性 解读 Autoreverses 设定这个属性为 YES 时,在它到达目的 ...

  6. php在web端播放amr语音(如微信语音)

    在使用微信JSSDK的上传下载语音接口时,发现一个问题: 下载的语音在iPhone上不能播放,测试了之后原因竟然是: 微信接口返回的音频内容是amr格式的,但iPhone不支持播放此类型格式. 那么转 ...

  7. 我的Android进阶之旅------>如何为ListView组件加上快速滑块以及修改快速滑块图像

    使用布局文件需要将android:fastScrollEnabled="true" ,如下代码所示: <ListView android:id="@+id/list ...

  8. 显示HTML的版权符号

    最近有小伙伴问©符号在页面显示很小,于是去查看他的源代码 他在HTML代码里对应输入© 那么在页面里应该会正常显示版权符号,可是为什么会出现这种问题呢? 首先我想到页面在设计的时候,用的字体是宋体,就 ...

  9. linux 基础2-null,cut,wc,head,tail

    一. 特殊文件: /dev/null和/dev/tty Linux系统提供了两个对Shell编程非常有用的特殊文件,/dev/null和/dev/tty.其中/dev/null将会丢掉所有写入它的数据 ...

  10. C#泛型命名潜规则

    public class List<T>{} public class LinkedList<T>{} public class SortedList<TKey,TVal ...