社区讨论

模拟退火求看❤

P4035[JSOI2008] 球形空间产生器参与者 4已保存回复 11

讨论操作

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

当前回复
11 条
当前快照
1 份
快照标识符
@lo19g35m
此快照首次捕获于
2023/10/22 17:22
2 年前
此快照最后确认于
2023/11/02 17:24
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace Testify{
    inline int read(){
        int f(1),x(0);
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
        return f*x;
    }
    inline void WritE(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) WritE(x/10);
        putchar(x%10+48);
    }
    inline void write(int x){
        WritE(x);
        puts("");
    }
    inline void Write(int x){
        WritE(x);
        putchar(' ');
    }
}
using namespace Testify;
int n;
mt19937 rd(chrono::high_resolution_clock::now().time_since_epoch().count());
inline int radom(int l,int r){
    return rd()%(r-l+1)+l;
}
const int N=12;
double x[N][N],Ans[N],ans,now[N];
inline double energy(){
    double sum=0;
    for(register int i=1;i<=n+1;i++){
        double res=0;
        for(register int j=1;j<=n;j++){
            res+=(now[j]-x[i][j])*(now[j]-x[i][j]);
        }
        res=sqrt(res);
        sum+=res;
    }
    return sum;
}
inline void SA(){
    double T=1;
    while(T>1e-15){
        if((double)clock()/CLOCKS_PER_SEC>0.99){
            for(register int i=1;i<=n;i++){
                printf("%.3lf ",Ans[i]);
            }
            exit(0);
        }
        int ra=radom(1,n);
        double yuan=now[ra];
        IZANA:;
        now[ra]=now[ra]+(radom(0,20000)*2-20000)*T;
        if(abs(now[ra])>20000){
            T*=0.985;
            goto IZANA;
        }
        // cerr<<now[ra]<<endl;
        double e=energy();
        double delta=e-ans;
        if(delta<0){
            ans=e;
            for(register int i=1;i<=n;i++){
                Ans[i]=now[i];
            }
        }
        else if(exp(-delta/T)*RAND_MAX<radom(0,RAND_MAX)){
            now[ra]=yuan;
        }
        T*=0.99995;
    }
}
signed main(void){
    n=read();
    for(register int i=1;i<=n+1;i++){
        for(register int j=1;j<=n;j++){
            scanf("%lf",&x[i][j]);
        }
    }
    ans=energy();
    while(1){
        SA();
    }
    return 0;
}   
按正常思路打的,但是一直随机到极大的数,求教教怎么做

回复

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

正在加载回复...