模拟退火(bzoj 3680: 吊打XXX)
2017-07-16 00:38
309 查看
3680: 吊打出题人
Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 3210 Solved: 1209
[Submit][Status][Discuss]
Description
gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty。gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了。蒟蒻们将n个gty吊在n根绳子上,每根绳子穿过天台的一个洞。这n根绳子有一个公共的绳结x。吊好gty后蒟蒻们发现由于每个gty重力不同,绳结x在移动。蒟蒻wangxz脑洞大开的决定计算出x最后停留处的坐标,由于他太弱了决定向你求助。不计摩擦,不计能量损失,由于gty足够矮所以不会掉到地上。
Input
输入第一行为一个正整数n(1<=n<=10000),表示gty的数目。接下来n行,每行三个整数xi,yi,wi,表示第i个gty的横坐标,纵坐标和重力。
对于20%的数据,gty排列成一条直线。
对于50%的数据,1<=n<=1000。
对于100%的数据,1<=n<=10000,-100000<=xi,yi<=100000
Output
输出1行两个浮点数(保留到小数点后3位),表示最终x的横、纵坐标。Sample Input
30 0 1
0 2 1
1 1 1
Sample Output
0.577 1.000看了几篇讲模拟退火的博客or论文,感觉是个很高端的随机方法
(有一篇很好的博文)http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html
像这道题:题目的大概意思就是给n个点,求出这n个点的重心坐标
其中重心满足:∑(重心与质点i的距离*质点i的质量)①最小
步骤:
一开始先大致估计一下重心的位置(x, y)为所有质点横纵坐标的平均值
然后不停随机,每次在离(x, y)不超过T的范围内找一点(x', y')判断是否更可能是重心(①的值更小)
如果是,则采用新的点作为当前重心,其中每随机完一次后都会减小T的值,当T小于一个定值时结束并输出当前重心
但这可能困于局部最优解,因此模拟退火比爬山算法多了一步:不是每次都一定取最优的那一点,而是一定概率无脑选择新的点,并且这个概率随着L越来越小也会越来越小,这样就可能跳出当前的局部最优
#include<stdio.h> #include<math.h> #include<stdlib.h> using namespace std; typedef struct Point { double x, y; double val; }Point; Point s[10010], ans; int n; double bet; double dis(Point x, Point y) { return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y)); } double Judge(Point p) { int i; double re=0; for(i=1;i<=n;i++) re += s[i].val*dis(p, s[i]); if(re<bet) ans = p, bet = re; return re; } double Rand() { return rand()%1000/1000.0; } void SA(double T) { int i; Point now; double dx; now = ans; while(T>0.001) { Point temp; temp.x = now.x+T*(Rand()*2-1); temp.y = now.y+T*(Rand()*2-1); dx = Judge(now) - Judge(temp) ; if(dx>0 || exp(dx/T)>Rand()) now = temp; T *= 0.993; } for(i=1;i<=1000;i++) { Point temp; temp.x = ans.x+T*(Rand()*2-1); temp.y = ans.y+T*(Rand()*2-1); Judge(temp); } } int main(void) { int i; while(scanf("%d", &n)!=EOF) { bet = 28104537678566885ll; for(i=1;i<=n;i++) { scanf("%lf%lf%lf", &s[i].x, &s[i].y, &s[i].val); ans.x += s[i].x; ans.y += s[i].y; } ans.x /= n; ans.y /= n; SA(1000000); printf("%.3lf %.3lf\n", ans.x, ans.y); } return 0; }
相关文章推荐
- BZOJ_3680_吊打XXX_模拟退火
- bzoj 3680 吊打xxx 模拟退火
- bzoj 3680 吊打xxx 模拟退火
- 【BZOJ3680】吊打XXX(模拟退火)
- 【BZOJ3680】吊打XXX(模拟退火)
- BZOJ 3680 吊打XXX 模拟退火
- [省选前题目整理][BZOJ 3680]吊打XXX(模拟退火)
- bzoj3680: 吊打XXX(模拟退火)
- [BZOJ3680]吊打XXX(模拟退火)
- [bzoj3680] 吊打XXX:模拟退火 or 模拟力学情景
- [BZOJ 3680]吊打XXX(广义费马点、模拟退火搜索)
- BZOJ 3680 吊打XXX
- [JSOI2004]平衡点/[BZOJ3680]吊打XXX
- BZOJ 3680 吊打XXX
- [bzoj3680]吊打XXX_模拟退火
- bzoj3680: 吊打XXX
- 【BZOJ3680】吊打XXX 广义费马点 模拟退火
- [BZOJ 3680] 吊打XXX 【模拟退火】
- BZOJ 3680 吊打XXX
- 【BZOJ3680】吊打xxx [模拟退火]