社区讨论

神奇模拟淬火

P1337[JSOI2004] 平衡点 / 吊打XXX参与者 4已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mi1a37zo
此快照首次捕获于
2025/11/16 13:31
3 个月前
此快照最后确认于
2025/11/17 09:10
3 个月前
查看原帖
https://www.luogu.com.cn/discuss/1198672
这个帖子的奆佬提出了模拟淬火,于是我动手实现了一下,发现正确率还是可以的。
但是理论上来说,刚开始时搜的比较密集,而后期就不密集了,应该难以得到正确答案,但是我的代码却能够得到69~100分的成绩
code:
CPP
#include<bits/stdc++.h>
using namespace std;
int n;
int x[1009];
int y[1009];
int w[1009];

double ansx, ansy, answ;

double engery(double _x, double _y) {
    double r = 0, dx, dy;
    for(int i = 1; i <= n; i++) {
        dx = _x - x[i];
        dy = _y - y[i];
        r += sqrt(dx * dx + dy * dy) * w[i];
    }
    return r;
}

void sa() {
    double t = 1e-15;
    while(t <= 3000) {
        double ex = ansx + (rand() * 2.0 - RAND_MAX)*t;
        double ey = ansy + (rand() * 2.0 - RAND_MAX)*t;
        double ew = engery(ex, ey);
        double de = ew - answ;
        if(de < 0) {
            ansx = ex;
            ansy = ey;
            answ = ew;
        }else if(exp(-de/t) * RAND_MAX > rand()) {
            ansx = ex;
            ansy = ey;
        }
        t*=1.003;
         
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    srand(time(0));
    
    cin >> n;
    for(int i = 1; i <= n; i++) {
        cin >> x[i] >> y[i] >> w[i];
        ansx += x[i];
        ansy += y[i];
    }    
    ansx/=n;
    ansy/=n;
    answ = engery(ansx, ansy);
    while((double)clock()/CLOCKS_PER_SEC<0.95)sa();
    printf("%.3lf %.3lf",ansx,ansy);
    return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...