题面传送门

解决思路

本题数据范围较小,可以使用模拟退火算法(随机化)。

顾名思义,模拟退火就是一个类似于降温的过程。先设置一个较大的初温,每次随机改变状态,若使答案更优,则采取更优答案,否则根据其与当前最优答案的差值,一定概率保留这个较不优的答案。这时为了防止答案陷入局部最优的情况:

比如下图,陷入局部最优解 \(1\) 的状态后,需要一定的概率跳出来(蓝色虚线),到 \(2\) 处寻找全局最优解。

关于跳出的概率,遵循 『 \(\text{Metropolis}\) 接受准则 』:

设 \(delta=\) 之前最优答案 \(-\) 当前答案,\(T\) 为当前温度。

若 \(p=exp({delta}\div{T})\) 大于 \(\lbrack\ 0,1 )\) 区间的随机数,则仍接受当前状态。

注:\(exp(x)\) 函数:求 \(e\) 的 \(x\) 次方的函数。\(e\) 是一个常数,等于 \(2.718281828…\)

至于为什么,有兴趣可以自己搜索,我们暂且认为这是一种很好的更新方式。


那么再看本题,我们就可以用模拟退火的方法不断随机“费马点”的坐标,得到最优解。

说一下退火的一些基本套路:

  • 初温一般设为 \(1000\sim3000\),每次降温的系数一般在 \(0.95\sim0.9975\) 之间,温度下限一般取 \(1e-15\)。可根据数据范围需要和时限做调整。

  • 除非你是究极无敌大欧皇,在时间允许情况下,一般建议退火 \(5\sim10\) 次取最优解。

  • 对空间类问题,初始的 \(ans\) 一般设为所有点横、纵坐标的平均值。每次调整方法(以横坐标为例):\(new_x=ans_x+(rand()\times2-\texttt{RAND\_MAX})\times t\),其中 \(ans_x\) 为之前最优横坐标,\(rand()\times2-\texttt{RAND\_MAX}\) 可以取到 \(-\texttt{RAND\_MAX}\sim \texttt{RAND\_MAX}\) 之间的随机数。乘 \(t\) (当前温度)是为了控制调整幅度。

对于本题,可知 \(ans_x<=max_x\),\(ans_y<=max_y\),为了防止刚开始的几次随机到较大的无用结果,我们可以将 \(new_x\) 取模 \(max_x\),\(new_y\) 取模 \(max_y\),用 \(fmod()\) 函数即可。

根据笔者试验,在 初温 \(=1000\),降温系数 \(=0.975\),退火 \(5\) 次的情况下可以 \(0\ \text{ms}\) 通过本题。

还有,虽然答案要求保留整数,但直接用 \(\text{int}\) 会导致精度丢失。所以都用 \(\text{double}\),输出答案时四舍五入\((int)(ans+0.5)\) 即可。

最后,注意多测的清空与额外换行!

AC Code:

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
#define db double
using namespace std;
db n,ansx,ansy;
db x[105],y[105],ans,mxx,mxy;
int tt,T,ANS;
db dis(db x1,db y1,db x2,db y2){
db d1=(x1-x2),d2=(y1-y2);
return sqrt(d1*d1+d2*d2);
}
db calc(db xx,db yy){
db sum=0;
for(int i=1;i<=n;i++) sum+=dis(xx,yy,x[i],y[i]);
return sum;
}
void sa(){
db t=1000,dw=0.975;
while(t>1e-15){
db tx=fmod(ansx+(rand()*2.0-(db)RAND_MAX)*t,mxx);
db ty=fmod(ansy+(rand()*2.0-(db)RAND_MAX)*t,mxy);
db m=calc(tx,ty);
db delta=ans-m;
if(delta>0) ans=m,ansx=tx,ansy=ty;
else if((db)rand()<(db)RAND_MAX*(db)exp(delta/t)) ansx=tx,ansy=ty;
t*=dw;
}
}
void solve(){
cin>>n;
ansx=0,ansy=0;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
mxx=max(mxx,x[i]),mxy=max(mxy,y[i]);
ansx+=x[i],ansy+=y[i];
}
ansx/=n,ansy/=n;
ans=calc(ansx,ansy);
tt=5;
while(tt--) sa();
cout<<(int)(ans+0.5)<<endl;
if(T) cout<<endl;
}
int main(){
IOS;TIE;
srand(time(NULL));
cin>>T;
while(T--) solve();
return 0;
}

【题解】UVA10228 A Star not a Tree?的更多相关文章

  1. UVA10228 A Star not a Tree?

    [返回模拟退火略解] 题目描述 一平面上有 nnn 个点 {Ai}\{A_i\}{Ai​},求一个点 XXX 使得σ=∑i=1ndis(Ai,X)\sigma=\sum_{i=1}^{n}{dis(A ...

  2. [模拟退火][UVA10228] A Star not a Tree?

    好的,在h^ovny的安利下做了此题 模拟退火中的大水题,想当年联赛的时候都差点打了退火,正解貌似是三分套三分,我记得上一道三分套三分的题我就是退火水过去的... 貌似B班在讲退火这个大玄学... 这 ...

  3. POJ 2420 A Star not a Tree? 爬山算法

    B - A Star not a Tree? Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/co ...

  4. pojA Star not a Tree?

    题目链接 pojA Star not a Tree? 题解 啊,模拟退火是个好东西 模拟退火即可 代码 #include<cmath> #include<cstdio> #in ...

  5. POJ 2420:A Star not a Tree?

    原文链接:https://www.dreamwings.cn/poj2420/2838.html A Star not a Tree? Time Limit: 1000MS   Memory Limi ...

  6. [POJ 2420] A Star not a Tree?

    A Star not a Tree? Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4058   Accepted: 200 ...

  7. POJ 2420 A Star not a Tree? (计算几何-费马点)

    A Star not a Tree? Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3435   Accepted: 172 ...

  8. uva 10228 - Star not a Tree?(模拟退火)

    题目链接:uva 10228 - Star not a Tree? 题目大意:给定若干个点,求费马点(距离全部点的距离和最小的点) 解题思路:模拟退火算法,每次向周围尝试性的移动步长,假设发现更长处, ...

  9. 模拟退火算法A Star not a Tree?(poj2420)

    http://write.blog.csdn.net/postedit A Star not a Tree? Time Limit: 1000MS   Memory Limit: 65536K Tot ...

随机推荐

  1. java方法---定义,调用

    定义,调用 1.方法的定义 方法就是一段用来完成特定功能的代码片段,类似于其它语言的函数. 方法用于定义该类或该类的实例的行为特征和功能实现.方法是类和对象行为特征的抽象. 方法很类似于面向过程中的函 ...

  2. pod资源的健康检查-readiness探针的httpGet使用

    livenessProbe:健康状态检查,周期性检查服务是否存活,检查结果失败,将重启容器 readinessProbe:可用性检查,周期性检查服务是否可用,不可用将从service的endpoint ...

  3. SpringMVC 01: SpringMVC + 第一个SpringMVC项目

    SpringMVC SpringMVC概述: 是基于MVC开发模式的框架,用来优化控制器 是Spring家族的一员,也具备IOC和AOP 什么是MVC: 它是一种开发模式,是模型视图控制器的简称,所有 ...

  4. Docker 搭建 Nexus3 私服 | 基本操作

    1 Docker 安装 Nexus3 1.1 创建目录 在硬盘上创建 Nexus3 的主目录: mkdir -p /Users/yygnb/dockerMe/nexus3 为该目录添加权限: chmo ...

  5. Typora 最后免费版本也不能用了?简单一招搞定

    作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.JAVA底层.面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 Typora是一款优秀的 Markdown 编辑 ...

  6. day36-IO流03

    JavaIO流03 4.常用的类02 4.4节点流和处理流 4.4.1基本介绍 节点流可以从一个特定的数据源读写数据,如FileReader.FileWriter 数据源就是存放数据的地方,比如文件. ...

  7. 类似微信聊天小程序-网易云信,IM DEMO小程序版本

    类似微信聊天小程序-网易云信,IM DEMO小程序版本 代码地址: https://github.com/netease-im/NIM_Web_Weapp_Demo 云信IM DEMO 小程序版本 ( ...

  8. 2.Python环境搭建

    Python是一个跨平台.可移植的编程语言,因此可在windows.linux/unix和Mac os x系统中安装使用.安装完成后,你会得到Python解释器环境,一个命令行交互环境,一个简单的集成 ...

  9. 6.云原生之Docker容器Registry私有镜像仓库搭建实践

    转载自:https://www.bilibili.com/read/cv15219863/?from=readlist #1.下载registry仓库并设置数据存放的目录(并生成认证账号密码) doc ...

  10. Linux恢复误删除的文件或者目录

    文章转载自:https://www.jianshu.com/p/662293f12a47 linux不像windows有个回收站,使用rm -rf *基本上文件是找不回来的. 那么问题来了: 对于li ...