我对模拟退火的理解: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. IOS navigationItem 设置返回button,title图片和rightBarButtonItem

    1.自己定义返回button UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" st ...

  2. J.U.C重入锁

    ReentrantLock重入锁 ReentrantLock是Java并发包中互斥锁,它有公平锁和非公平锁两种实现方式, 重入的意思就是,如果已经获得了锁,如果执行期间还需要获得这个锁的话,会直接获得 ...

  3. AbstractQueuedSynchronizer(一)

    应该将子类定义为非公共内部帮助器类,一般并发包类用内部类Sync sync来继承并实现.为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量.事件,等等)提供一个框架.此类的设计目 ...

  4. ubuntu13.04中把ibus中的中文拼音输入设为默认

    全新的ubuntu ,先选择 下载服务器 首选项->软件和更新 选择 最佳服务器 准备工作:卸载Ubuntu默认的ibus输入法: sudo apt-get remove ibus 然后添加Fc ...

  5. javascript常见的20个问题与解决方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. Gateway

    网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连.网关的结构也和路由器类似,不同的是互连层.网关既可以用于广域网互连,也可以用于局域网互连. 网关是一种充当转换重 ...

  7. 使用Pydoc生成文档

    Python中本身带有很多实用的工具,如pydoc.pydoc模块主要用来从Python模块中提取信息并生成文档. 使用方法 在Windows和Linux下的使用方法有些区别. Windows pyt ...

  8. Render树、RenderObject与RenderLayer

    Chapter: 呈现树的构建 1. 呈现树与CSS盒子模型千丝万缕的关系 2. 呈现树与DOM树的关系 3. 浏览器构建呈现树的流程 4. Firefox的规则树和样式上下文树 5. 规则树是如何解 ...

  9. CustomizaitonSpec Clone_VM

    克隆虚拟机可以加上CustomizationSpec来自动配置好:IP地址.DNS.Domain等信息 1.可以利用PyVmimo中的vim模块在python中完全自定义CustomizationSp ...

  10. 命令行 -- 命令"%cd%"

    1. @echo off echo 当前盘符:%~d0 echo 当前盘符和路径:%~dp0 echo 当前批处理全路径:%~f0 echo 当前盘符和路径的短文件名格式:%~sdp0 echo 当前 ...