题面传送门

解决思路

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

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

比如下图,陷入局部最优解 \(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. DES|3DES|AES|RSA|DH | CA | SSL(HTTPS)

    1.对称密钥算法: 加解密速度块,算法使安全的,已知算法无法推出密钥.但是密钥的分发困难. DES:对称密钥算法,是一种块加密算法,只有一个密钥.加解密都是用一个密钥. 3DES:与DES一样,可以认 ...

  2. Qt编程选择QtCreator还是Qt+VS

    结论:推荐QtCreator 对于一个新手而言,基本体会如下: Qt Creator Qt Creator优势 可以实现Ui和代码无缝切换.(VS不行) 对于汉字的支持更好 提示功能做的更好. 比如: ...

  3. flutter系列之:Material主题的基础-MaterialApp

    简介 为了简化大家的使用,虽然flutter推荐所有的widget都有自己来进行搭建,但是在大框架上面,flutter提供了Material和Cupertino两种主题风格的Widgets集合,大家可 ...

  4. Arrays.asList()你真的知道怎么用吗?

    发现问题 前几天在看别人的项目的时候,发现一个问题,简单复现一下这个问题 // 注意这是一个Integer对象的数组哦 Integer[] arr = new Integer[]{9999,88,77 ...

  5. Job And Schedule (V8R6C4)

    KingbaseES 数据库提供了 kdb_schedule 扩展,使得用户能通过类似oracle job 的方式进行job调用.kdb_schedule 提供了三个Schema :dbms_job ...

  6. 数据库基础操作-part2

    单表和多表查询 单表查询 记录详细操作: 增 insert into t1(字段1, 字段2, 字段3) values (值1, 值2, 值3), (值1, 值2, 值3), (值1, 值2, 值3) ...

  7. 跟我学Python图像处理丨关于图像金字塔的图像向下取样和向上取样

    摘要:本文讲述图像金字塔知识,了解专门用于图像向上采样和向下采样的pyrUp()和pyrDown()函数. 本文分享自华为云社区<[Python图像处理] 二十一.图像金字塔之图像向下取样和向上 ...

  8. SQL 时间范围和时间粒度

    前言 使用 SQL 进行业务数据计算时,经常会遇到两个概念:时间范围 和 时间粒度 .以 最近一天的每小时的用户访问人数 为例: 最近一天 是时间范围 每小时 是时间粒度 常见的时间范围:最近五分钟. ...

  9. Python解释器路径寻找规则

    Python编辑器路径寻址总结 Python编程优化 这场表演邀请了三位角色:run.sh.main.py.path.sh,拍摄场地选在了 Windows -> Git Bash 群演1号 ru ...

  10. 浅谈 Golang 插件机制

    我们知道类似 Java 等半编译半解释型语言编译生成的都是类似中间态的字节码,所以在 Java 里面我们想要实现程序工作的动态扩展,可以通过 Java 的字节码编辑技术([[动态代理#ASM]]/[[ ...