我们都爱膜您退火!

写了模板题(伪)洛谷P1337 平衡点,发现这跟骑行川藏毫无可比性......

骑行川藏简直就是退火地狱,这个模板题就容易的多了...随便搞几下就过了。

一些心得:

1.最好在函数值连续的时候使用模拟退火。

2.想要把精度控制的高,重要的不是eps,而是把△T调小。这样在T很小的时候会随机足够多的次数从而让精度更进一步。

3.正确性的核心在于每次随机调整出来的解的变化幅度与T相关。

例题:骑行川藏

洛谷P1337,这东西很好退吧...

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 1010;
  4 const double eps = 1e-7, dT = 0.999;
  5 
  6 struct Vec {
  7     double x, y;
  8     Vec(double X = 0, double Y = 0) {
  9         x = X, y = Y;
 10     }
 11     inline Vec operator + (const Vec &w) const {
 12         return Vec(x + w.x, y + w.y);
 13     }
 14     inline Vec operator - (const Vec &w) const {
 15         return Vec(x - w.x, y - w.y);
 16     }
 17     inline double operator & (const Vec &w) const {
 18         return x * w.x + y * w.y;
 19     }
 20     inline double operator * (const Vec &w) const {
 21         return x * w.y - y * w.x;
 22     }
 23     inline Vec operator * (const double &w) const {
 24         return Vec(x * w, y * w);
 25     }
 26     inline Vec operator / (const double &w) const {
 27         return Vec(x / w, y / w);
 28     }
 29 };
 30 typedef Vec Poi;
 31 
 32 Poi a[N];
 33 int n;
 34 double W[N];
 35 
 36 inline double len(Vec x) {
 37     return sqrt(x & x);
 38 }
 39 
 40 inline double cal(double x, double y) {
 41     //printf("cal : %lf %lf \n", x, y);
 42     Vec ans(0, 0), now(x, y);
 43     for(int i = 1; i <= n; i++) {
 44         if(fabs(y - a[i].y) < eps && fabs(x - a[i].x) < eps) continue;
 45         Vec temp = (a[i] - now) / len(a[i] - now) * W[i];
 46         ans = ans + temp;
 47     }
 48     /*printf("ansx = %lf ansy = %lf \n", ans.x, ans.y);
 49     puts("");*/
 50     return len(ans);
 51 }
 52 
 53 inline double Rand(double l, double r) {
 54     return (double)rand() / RAND_MAX * (r - l) + l;
 55 }
 56 
 57 inline void Fire() {
 58     double x1 = 1e7, x2 = -1e7, y1 = 1e7, y2 = -1e7;
 59     for(int i = 1; i <= n; i++) {
 60         x1 = std::min(x1, a[i].x);
 61         x2 = std::max(x2, a[i].x);
 62         y1 = std::min(y1, a[i].y);
 63         y2 = std::max(y2, a[i].y);
 64     }
 65 
 66     double px((x2 + x1) / 2), py((y2 + y1) / 2), fx(px), fy(py), T(std::max(y2 - y1, x2 - x1));
 67     double ans = cal(px, py), fin = ans;
 68 
 69     while(T > eps) {
 70 
 71         double x = px + T * Rand(-1, 1), y = py + T * Rand(-1, 1);
 72         x = std::max(x, x1);
 73         x = std::min(x, x2);
 74         y = std::max(y, y1);
 75         y = std::min(y, y2);
 76         double New = cal(x, y);
 77         //printf("New = %lf \n", New);
 78 
 79         if(New < fin) {
 80             fin = New;
 81             fx = x;
 82             fy = y;
 83         }
 84         if(New < ans || Rand(0, 1) < exp((ans - New) / T)) {
 85             ans = New;
 86             px = x;
 87             py = y;
 88         }
 89         /*printf("fin = %lf fx = %lf fy = %lf\n", fin, fx, fy);
 90         printf("ans = %lf px = %lf py = %lf\n", ans, px, py);
 91         printf("T = %lf New = %lf \n", T, New);
 92         puts("");*/
 93         T *= dT;
 94     }
 95     printf("%.3f %.3f\n", fx, fy);
 96     return;
 97 }
 98 
 99 int main() {
100     scanf("%d", &n);
101     for(int i = 1; i <= n; i++) {
102         scanf("%lf%lf%lf", &a[i].x, &a[i].y, &W[i]);
103     }
104 
105     Fire();
106 
107     return 0;
108 }
AC代码

猜你喜欢

转载自www.cnblogs.com/huyufeifei/p/10811122.html