BZOJ 3680: 吊打XXX // Luogu [JSOI2004]平衡点 / 吊打XXX (模拟退火)
第一次写模拟退火…
这是在BZOJ上过了的(在luogu上会WA)
CODE1
#include<bits/stdc++.h>
using namespace std;
inline void read(int &num) {
char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg = -flg;
for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar()); num*=flg;
}
const int MAXN = 10005;
struct point {
double x, y;
point(){}
point(double x, double y):x(x), y(y){}
}ans, p[MAXN];
double w[MAXN], mins = 1e100; int n;
inline double getrd() { return rand() % 10000 / 10000.0; } //[0,1)
inline double sqr(const double &x) { return x*x; }
inline double dist(const point &A, const point &B) {
return sqrt(sqr(A.x-B.x) + sqr(A.y-B.y));
}
inline double chk(const point &a) {
double re = 0;
for(int i = 1; i <= n; ++i)
re += dist(a, p[i]) * w[i];
if(re < mins) mins = re, ans = a;
return re;
}
inline void SA() {
point now = ans;
double T = 100000;
while(T > 1e-3) {
point newp;
newp.x = now.x + T*(getrd()*2-1.0);
newp.y = now.y + T*(getrd()*2-1.0);
double delta = chk(now)-chk(newp);
if(delta > 0 || exp(delta/T) > getrd()) now = newp;
T *= 0.991;
}
for(int i = 1; i <= 520; ++i) {
point newp;
newp.x = ans.x + T*(getrd()*2-1.0);
newp.y = ans.y + T*(getrd()*2-1.0);
chk(newp);
}
}
int main() {
srand(23333333);
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%lf%lf%lf", &p[i].x, &p[i].y, &w[i]);
ans.x += p[i].x, ans.y += p[i].y;
}
ans.x /= n, ans.y /= n;
SA();
printf("%.3f %.3f\n", ans.x, ans.y);
}
这是在Luogu上过了的(在BZOJ上会T)
CODE2
#include<bits/stdc++.h>
using namespace std;
inline void read(int &num) {
char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg = -flg;
for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar()); num*=flg;
}
const int MAXN = 10005;
struct point {
double x, y;
point(){}
point(double x, double y):x(x), y(y){}
}ans, p[MAXN];
double w[MAXN], mins = 1e100; int n;
inline double getrd() { return rand() % 10000 / 10000.0; } //[0,1)
inline double sqr(const double &x) { return x*x; }
inline double dist(const point &A, const point &B) {
return sqrt(sqr(A.x-B.x) + sqr(A.y-B.y));
}
inline double chk(const point &a) {
double re = 0;
for(int i = 1; i <= n; ++i)
re += dist(a, p[i]) * w[i];
if(re < mins) mins = re, ans = a;
return re;
}
inline void SA() {
point now = ans;
for(int i = 1; i <= 10; ++i) { //多来几次...
double T = 100000;
while(T > 1e-3) {
point newp;
newp.x = now.x + T*(getrd()*2-1.0);
newp.y = now.y + T*(getrd()*2-1.0);
double delta = chk(now)-chk(newp);
if(delta > 0 || exp(delta/T) > getrd()) now = newp;
T *= 0.991;
}
for(int i = 1; i <= 520; ++i) {
point newp;
newp.x = ans.x + T*(getrd()*2-1.0);
newp.y = ans.y + T*(getrd()*2-1.0);
chk(newp);
}
}
}
int main() {
srand(23333333);
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%lf%lf%lf", &p[i].x, &p[i].y, &w[i]);
ans.x += p[i].x, ans.y += p[i].y;
}
ans.x /= n, ans.y /= n;
SA();
printf("%.3f %.3f\n", ans.x, ans.y);
}