洛谷 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; }