【模拟退火】洛谷 P1337 平衡点 吊打XXX
2021-06-01 17:00:00 # ACM

题链

随即确定一个点,将其他点对该点产生的力正交分解,试能越小越稳定;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define PI acos(-1.0)
#define eps 1e-8
#define Pair pair<double,double>
// notice
#define mod 998244353
#define MAXN 1e18
#define MS 100009

LL n,m;
struct node{
double x,y,w;
}p[MS];
node ans;

double cal(node t){// 计算试能
double cc = 0;
for(int i=1;i<=n;i++){
double dx = p[i].x - t.x;
double dy = p[i].y - t.y;
cc += sqrt(dx*dx+dy*dy)*p[i].w;
}
return cc;
}

void simulate(){
for(double T=3000,r=0.9;T>1e-15;T*=r){
node o;
o.x = ans.x + T*(rand()*2-RAND_MAX);
o.y = ans.y + T*(rand()*2-RAND_MAX);
o.w = cal(o);
double cha = o.w - ans.w;
if(cha < 0){
ans = o;
}
else if(exp(-cha/T)*RAND_MAX>rand()){
ans.x = o.x;
ans.y = o.y;
}
}
}

int main() {
//ios::sync_with_stdio(false);
srand(unsigned(time(0)));
cin >> n;
for(int i=1;i<=n;i++){
double x,y,w;
cin >> x >> y >> w;
p[i] = {x,y,w};
ans.x += x;
ans.y += y;
}

ans.x /= n;
ans.y /= n;
ans.w = cal(ans);
LL cnt = 300;
while(cnt--) simulate();

printf("%.3f %.3f\n",ans.x,ans.y);
// cout << ans.x << " " << ans.y << "\n";

return 0;
}

Prev
2021-06-01 17:00:00 # ACM
Next