写了模板题(伪)洛谷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 }