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);
}
posted @ 2019-12-14 14:50  _Ark  阅读(113)  评论(0编辑  收藏  举报