[BZOJ3680][JSOI2004]平衡点 / 吊打XXX
2018-02-06 20:21
465 查看
BZOJ
Luogu
(洛谷和BZOJ上的数据范围不同,可能需要稍微调一调参数)
模拟退火的模型可以形象地理解为:不断降温的小球在一个凹凸不平的平面上反复横跳,根据万有引力定理小球一定会停留在一个低洼的位置。在温度高的时候小球的运动幅度剧烈,同时也较容易地会接受更劣的解(也就是一个更高的位置)。随着温度降低小球的运动幅度减小,变得较难以接受一个更劣的解。
因为这题的背景下较优解会比较集中,所以在降温达到指定温度后要向四周多rand几次。
Luogu
(洛谷和BZOJ上的数据范围不同,可能需要稍微调一调参数)
sol
这题的参数调得我心累模拟退火的模型可以形象地理解为:不断降温的小球在一个凹凸不平的平面上反复横跳,根据万有引力定理小球一定会停留在一个低洼的位置。在温度高的时候小球的运动幅度剧烈,同时也较容易地会接受更劣的解(也就是一个更高的位置)。随着温度降低小球的运动幅度减小,变得较难以接受一个更劣的解。
因为这题的背景下较优解会比较集中,所以在降温达到指定温度后要向四周多rand几次。
code
#include<cstdio> #include<algorithm> #include<ctime> #include<cmath> using namespace std; const int N = 1005; struct node{double x,y,w,tot;}p ,ans; int n; double sqr(double x){return x*x;} double dist(node a,node b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));} double calc(node P) { double res=0; for (int i=1;i<=n;i++) res+=p[i].w*dist(P,p[i]); return res; } double Rand(){return rand()%100000/100000.0;} void SA(double T) { node now=ans,nw;double delta; while (T>1e-5) { nw.x=now.x+T*(2*Rand()-1); nw.y=now.y+T*(2*Rand()-1); nw.tot=calc(nw); if (nw.tot<now.tot||exp((now.tot-nw.tot)/T)>Rand()) now=nw; if (nw.tot<ans.tot) ans=nw; T*=0.99; } for (int i=1;i<=5000;i++) { nw.x=ans.x+T*(2*Rand()-1); nw.y=ans.y+T*(2*Rand()-1); nw.tot=calc(nw); if (nw.tot<ans.tot) ans=nw; } } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%lf %lf %lf",&p[i].x,&p[i].y,&p[i].w); ans.x+=p[i].x;ans.y+=p[i].y; } ans.x/=n;ans.y/=n;ans.tot=calc(ans); for (int i=1;i<=10;i++) SA(100000); printf("%.3lf %.3lf",ans.x,ans.y); return 0; }
相关文章推荐
- BZOJ3680 & 洛谷1337:[JSOI2004]平衡点/吊打XXX——题解
- [JSOI2004]平衡点/[BZOJ3680]吊打XXX
- [JSOI2004]平衡点 / 吊打XXX
- 洛谷P1337 【[JSOI2004]平衡点 / 吊打XXX】(模拟退火)
- [LuoguP1337] [JSOI2004]平衡点 / 吊打XXX
- P1337 [JSOI2004]平衡点 / 吊打XXX
- 【BZOJ3680】吊打xxx [模拟退火]
- [bzoj3680] 吊打XXX:模拟退火 or 模拟力学情景
- 【bzoj 3680】吊打XXX
- bzoj 3680 吊打xxx 模拟退火
- bzoj3680: 吊打XXX
- bzoj 3680 吊打xxx 模拟退火
- BZOJ 3680 吊打XXX
- 模拟退火(bzoj 3680: 吊打XXX)
- BZOJ3680 吊打XXX
- BZOJ3680 吊打xxx
- BZOJ3680 吊打XXX
- [bzoj3680]吊打XXX_模拟退火
- bzoj3680 吊打XXX
- bzoj3680: 吊打XXX