BZOJ3680: 吊打XXX

模拟退火裸题,爆了n发就是随机wa一个点。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int x[1010], y[1010], w[1010];
 4 double ansx, ansy, ans;
 5 inline double R() {
 6     return (double)rand() / RAND_MAX;
 7 }
 8 inline double calc(int n, double xx, double yy) {
 9     double ret = 0; 
10     for(int i = 1; i <= n; ++ i) {
11         double nx = xx - x[i], ny = yy - y[i];
12         ret += (double)sqrt(nx * nx + ny * ny) * w[i];
13     } if(ret < ans) {
14         ans = ret, ansx = xx, ansy = yy;
15     } return ret;
16 }
17 inline void Do(int n) {
18     double tem = 1e5, X = ansx, Y = ansy;
19     while(tem > 1e-4) {
20         double nx = X + tem * (R() - 0.5);
21         double ny = Y + tem * (R() - 0.5);
22         double delta = calc(n, nx, ny) - calc(n, X, Y);
23         if(exp(-delta / tem) > R()) {
24             X = nx, Y = ny;
25         }
26         tem = tem * 0.97;
27     } for(int i = 1; i <= 1000; ++ i) {
28         double nx = ansx + tem * (R() - 0.5);
29         double ny = ansy + tem * (R() - 0.5);
30         calc(n, nx, ny);
31     }
32 }
33 int main() {
34     srand(time(0));
35     int n; scanf("%d",&n);
36     for(int i = 1; i <= n; ++ i) {
37         scanf("%d%d%d", &x[i], &y[i], &w[i]);
38         ansx += x[i], ansy = y[i];
39     } ansx /= n, ansy /= n;
40     ans = calc(n, ansx, ansy);
41     for(int i = 1; i <= 100; ++ i) {
42         Do(n); 
43     }
44     printf("%.3lf %.3lf\n", ansx, ansy);
45 }
View Code

 

posted @ 2019-10-03 15:58  iamunstoppable  阅读(144)  评论(0编辑  收藏  举报