我们都爱膜您退火!

写了模板题(伪)洛谷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 
", 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 
", 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 
", 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
", fin, fx, fy);
 90         printf("ans = %lf px = %lf py = %lf
", ans, px, py);
 91         printf("T = %lf New = %lf 
", T, New);
 92         puts("");*/
 93         T *= dT;
 94     }
 95     printf("%.3f %.3f
", 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代码

LOJ#512 春游(提答)

题意:把n个小动物分成K组,使得每组的权值最大值最小。有m个约束形如两个小动物在一组会把权值 + a或者 × b,先加后乘。

解:用时约2h,得分69。

模拟退火。先随机分组,然后随机一个小动物改变到一个随机组里。权值的变化:枚举别的所有点,邻接矩阵存边权。权值的计算:每个组维护一个add和mul,暴力枚举所有组算权值。

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 100010;
  4 
  5 struct Node {
  6     int x, y, f, z;
  7     double w;
  8 }node[N];
  9 
 10 inline int rd(int l, int r) {
 11     return rand() % (r - l + 1) + l;
 12 }
 13 inline double Rand() {
 14     return (double)(rand()) / RAND_MAX;
 15 }
 16 
 17 int n, K, m, val[N], val2[N], testid;
 18 int fr[N], Fin[N];
 19 int G1[5010][5010], G2[5010][5010], add[N];
 20 double G3[5010][5010], mul[N];
 21 std::vector<int> v[N];
 22 
 23 inline double calMax() {
 24     double ans(0);
 25     for(register int i(1); i <= K; ++i) {
 26         ans = std::max(ans, mul[i] * add[i]);
 27     }
 28     return ans;
 29 }
 30 
 31 inline void Fire() {
 32     
 33     for(int i = 1; i <= K; i++) {
 34         add[i] += val2[i];
 35         mul[i] = 1;
 36     }
 37     for(int i = 1; i <= n; i++) {
 38         fr[i] = rd(1, K);
 39         add[fr[i]] += val[i];
 40         for(int j = 1; j < i; j++) {
 41             if(fr[i] != fr[j] || !G1[i][j]) {
 42                 continue;
 43             }
 44             if(G1[i][j] == 1) {
 45                 add[fr[i]] += G2[i][j];
 46             }
 47             else {
 48                 mul[fr[i]] *= G3[i][j];
 49             }
 50         }
 51     }
 52     
 53     double ans = calMax(), fin = ans;
 54     memcpy(Fin + 1, fr + 1, n * sizeof(int));
 55     
 56     double T = 10000, dT = 0.9999, edT = 1e-7;
 57     while(T > edT) {
 58         
 59         int x = rd(1, n), y = rd(1, K);
 60         while(y == fr[x]) {
 61             y = rd(1, K);
 62         }
 63         std::swap(fr[x], y);
 64         add[y] -= val[x];
 65         add[fr[x]] += val[x];
 66         for(int i = 1; i <= n; i++) {
 67             if(!G1[x][i] || (fr[i] != y && fr[i] != fr[x])) {
 68                 continue;
 69             }
 70             if(fr[i] == fr[x]) {
 71                 if(G1[x][i] == 1) {
 72                     add[fr[x]] += G2[x][i];
 73                 }
 74                 else {
 75                     mul[fr[x]] *= G3[x][i];
 76                 }
 77             }
 78             else {
 79                 if(G1[x][i] == 1) {
 80                     add[y] -= G2[x][i];
 81                 }
 82                 else {
 83                     mul[y] /= G3[x][i];
 84                 }
 85             }
 86         }
 87         double nex = calMax();
 88         //printf("T = %lf nex = %lf 
", T, nex);
 89         if(fin > nex) {
 90             fin = nex;
 91             memcpy(Fin + 1, fr + 1, n * sizeof(int));
 92             printf("fin = %lf 
", fin);
 93         }
 94         if(nex < ans || Rand() < exp((ans - nex) / T)) {
 95             ans = nex;
 96         }
 97         else {
 98             std::swap(fr[x], y);
 99             add[y] -= val[x];
100             add[fr[x]] += val[x];
101             for(int i = 1; i <= n; i++) {
102                 if(!G1[x][i] || (fr[i] != y && fr[i] != fr[x])) {
103                     continue;
104                 }
105                 if(fr[i] == fr[x]) {
106                     if(G1[x][i] == 1) {
107                         add[fr[x]] += G2[x][i];
108                     }
109                     else {
110                         mul[fr[x]] *= G3[x][i];
111                     }
112                 }
113                 else {
114                     if(G1[x][i] == 1) {
115                         add[y] -= G2[x][i];
116                     }
117                     else {
118                         mul[y] /= G3[x][i];
119                     }
120                 }
121             }
122         }
123         T *= dT;
124     }
125     
126     for(int i = 1; i <= n; i++) {
127         v[Fin[i]].push_back(i);
128     }
129     
130     char buf[100];
131     sprintf(buf, "spring%d.out", testid);
132     freopen(buf, "w", stdout); 
133     
134     for(int i = 1; i <= K; i++) {
135         int len = v[i].size();
136         printf("%d
", len);
137         for(int j = 0; j < len; j++) {
138             printf("%d ", v[i][j]);
139         }
140         puts("");
141     }
142     fclose(stdout);
143     return;
144 }
145 
146 int main(int argc, char **argv) {
147 
148     srand(time(0));
149 
150     if(argc != 2) return 0;
151     testid = atoi(argv[1]);
152     char buf[100];
153     sprintf(buf, "spring%d.in", testid);
154     freopen(buf, "r", stdin);
155 
156     scanf("%d%d%d", &n, &K, &m);
157     for(int i = 1; i <= n; i++) {
158         scanf("%d", &val[i]);
159     }
160     for(int i = 1; i <= K; i++) {
161         scanf("%d", &val2[i]);
162     }
163     for(int i = 1; i <= m; i++) {
164         scanf("%d%d%d", &node[i].f, &node[i].x, &node[i].y);
165         int x = node[i].x, y = node[i].y;
166         G1[x][y] = G1[y][x] = node[i].f;
167         if(node[i].f == 1) {
168             scanf("%d", &node[i].z);
169             G2[x][y] = G2[y][x] = node[i].z;
170         }
171         else {
172             scanf("%lf", &node[i].w);
173             G3[x][y] = G3[y][x] = node[i].w;
174         }
175     }
176     fclose(stdin);
177     
178     Fire();
179     
180     return 0;
181 }
代码
原文地址:https://www.cnblogs.com/huyufeifei/p/10811122.html