题面传送门

解决思路

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

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

比如下图,陷入局部最优解 \(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. CodeForces - 1690F

    Problem - F - Codeforces 题意: 给出一个字符串,给出一个序列,每次对应位置的字符变成序列指定位置的字符,即序列中对应位置为2,那么字符串的这个位置的字符就要变成字符串第二个位 ...

  2. python字典键或值去重

    from fuzzywuzzy import fuzz, process a = {'嫦娥四号探测器是用哪个型号的火箭发射的?': ['长征3B'], '嫦娥四号探测器是在我国[]发射成功的.': [ ...

  3. KingbaseES例程之拥有大量索引的表导入数据

    概述 如何快速插入大量数据比如几千万上亿的带索引的数据表. 数据准备 准备一个拥有二十个索引的数据表. kingbase=# \d+ bigtab Table "kingbase.bigta ...

  4. K8S_删除Pod总结

    K8S 不能直接删除Pod,直接删除Pod,会被Deployment重启 删除前,必须先删除对应的Deployment 例子: // 查出Pod [root@k8s-master ~]# kubect ...

  5. Linux零拷贝原理

    Linux零拷贝原理 前言 磁盘可以说是计算机系统最慢的硬件之一,读写速度相差内存 10 倍以上,所以针对优化磁盘的技术非常的多,比如零拷贝.直接 I/O.异步 I/O 等等,这些优化的目的就是为了提 ...

  6. Linux安装Minio

    Linux安装Minio 一.安装包方式安装 1.下载minio 1.1 手动下载:https://docs.min.io/docs/minio-quickstart-guide.html ​ 访问上 ...

  7. Github-CLI

    Github-CLI Github 的官方命令行工具 Github CLI.Mac 系统可以通过 homebrew 安装或者直接下载免安装包来使用. 命令 Github CLI 的所有命令均以gh开头 ...

  8. 有偿提供ES 7.X和8.X 版本 的白金版和企业版 使用咨询服务

    若有意向,可通过下方的邮箱发邮件进行咨询,非诚勿扰.. 邮箱地址:sandu12345@msn.cn

  9. 使用 Skywalking Agent,这里使用sidecar 模式挂载 agent

    文章转载自:https://bbs.huaweicloud.com/blogs/315037 方法汇总 Java 中使用 agent ,提供了以下三种方式供你选择 使用官方提供的基础镜像 将 agen ...

  10. krew插件安装

    概念 Krew是kubectl插件的包管理工具.借助Krew,可以轻松地使用kubectl plugin:发现插件.安装和管理插件.使用类似apt.dnf或者brew. 对于kubectl用户:kre ...