洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX

模拟退火模板题,我们的目标是minimize$$\sum^n_{i=1}dis[i]*weight[i]$$

其中$$dis[i]=distance(P_{ans},P_{i})$$

故相当于我们要在一个空间内找一个点$P_{ans}$,具有最优性质

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
class HOLE {
public:
    void Set(int _x, int _y, int _w) {
        x = _x;
        y = _y;
        w = _w;
    }
    double Wg(double X, double Y) {
        return sqrt((X - x) * (X - x) + (Y - y) * (Y - y)) * w;
    }
private:
    double x, y, w;
};
HOLE hole[1010];
double cal_val(double x, double y, int n) {
    double ret = 0;
    for (int i = 1; i <= n; i++) {
        ret += hole[i].Wg(x, y);
    }
    return ret;
}
void sa(double& x0, double& y0, int n) {
    double Temperature = 5000;
    double zeroT = 1e-15;
    double down_rate = 0.004;
    double ansval = cal_val(x0, y0, n);
    int cnt = 0;
    while (Temperature > zeroT) {
        double newx = x0 + (rand() * 2 - RAND_MAX) * Temperature;
        double newy = y0 + (rand() * 2 - RAND_MAX) * Temperature;
        double newval = cal_val(newx, newy, n);
        double delta_val = newval - ansval;
        if (delta_val < 0) {
            x0 = newx;
            y0 = newy;
            ansval = newval;
        }
        else if (rand() < exp(-delta_val / Temperature) * RAND_MAX) {
            x0 = newx;
            y0 = newy;
        }
        Temperature *= 1 - down_rate;
    }
}
int main() {
    srand(623223771);
    int n;
    cin >> n;
    double ansx = 0, ansy = 0;
    for (int i = 1; i <= n; i++) {
        int x, y, w;
        cin >> x >> y >> w;
        hole[i].Set(x, y, w);
        ansx += x;
        ansy += y;
    }
    ansx /= n;
    ansy /= n;
    for (int i = 1; i <= 5; i++) {
        sa(ansx, ansy, n);
    }
    printf("%.3lf %.3lf\n", ansx, ansy);
    return 0;
}

 

posted @ 2021-05-28 13:48  halfrot  阅读(60)  评论(0编辑  收藏  举报