• 我们都爱膜您退火!


    写了模板题(伪)洛谷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 }
    代码
  • 相关阅读:
    ICL7135的C程序
    数组属性的习题、Arrays工具、二维数组
    上传文件js端处理
    Java常见的系统路径与获取方法
    java 文件流的处理 文件打包成zip
    JAVA根据URL网址获取输入流
    nginx安装教程
    jackson 实体转json json字符串转实体
    java 对象重写tostring
    java 将文件流和文件名称转换为文件
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10811122.html
Copyright © 2020-2023  润新知