模拟退火大法

这个算法本身就不多讲了,感觉很暴力。

Luogu P5928

#include<bits/stdc++.h>
#define int long long
using namespace std;
const double eps=1e-3,delta=0.999;
const int N=103; 
int  n,p;
struct node{
    int a,b,c,w;
   bitset<N>v;
}e[104];
struct book{
    int x,y;
}z[103];
int Ans=1e18;
bitset<N>tmp,vis;
int calc(){
    int res=0;
    for(int i=1;i<=p;i++) vis[i]=0;
    for(int i=1;i<=n;i++){
        if(tmp[i]) vis|=e[i].v,res+=e[i].w;
    }
    for(int i=1;i<=p;i++) if(!vis[i]) return 2e9;
    return res;
}
void solve(){
    double T=2333;
    int ans=calc(),now=ans;
    while(T>eps){
        int x=rand()%n+1;
        tmp[x]=!tmp[x];
        int k=calc();
        if(k<ans) ans=k;
        if(k<now||exp((double)(now-k)/T)>(double)rand()/INT_MAX) now=k;
        else tmp[x]=!tmp[x];
        T*=delta; 
    }
    Ans=min(Ans,ans);
}
int a,b,c,w;
signed main(){
    srand(time(NULL));
    cin>>n>>p;
    for(int i=1;i<=n;i++){
        cin>>a>>b>>c>>w;
        e[i]={a,b,c,w,bitset<N>{}};
    }
    for(int i=1;i<=p;i++){
        cin>>z[i].x>>z[i].y;
    }
    for(int i=1;i<=n;i++){
        tmp[i]=1;
        for(int j=1;j<=p;j++){
            if(z[j].x*e[i].a+z[j].y*e[i].b<=e[i].c){
                e[i].v[j]=1;
            }
        }
    }
    if(calc()==2e9){
        cout<<"-1";
        return 0;
    }
    double timer=clock();
    while(clock()-timer<=CLOCKS_PER_SEC*0.98) solve();
    cout<<Ans;
}

Luogu P1337

#include<bits/stdc++.h>
using namespace std;
double x_ans,y_ans,ans;
int n;
double delta=0.999,Min=1e-14;
struct node{
    int x,y,w;
}z[3004];
unsigned long long seed=19491001;
double get(double x,double y){
    double dx=0,dy=0,res=0;
    for(int i=1;i<=n;i++){
        dx=x-z[i].x;
        dy=y-z[i].y;
        res+=sqrt(dx*dx+dy*dy)*z[i].w;
    }
    return res;
}
void solve(){
    double T=3100;
    while(T>Min){
        double x=x_ans+(rand()*2-RAND_MAX)*T;
        double y=y_ans+(rand()*2-RAND_MAX)*T;
        double w=get(x,y);
        if(w<ans){
            x_ans=x;
            y_ans=y;
            ans=w;
        }
        else if(exp((double)(ans-w)/T)>(double)rand()/RAND_MAX){
            x_ans=x;
            y_ans=y;
        }
        T*=delta;
    }
}
signed main(){
    ios::sync_with_stdio(false);
    srand(seed);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>z[i].x>>z[i].y>>z[i].w;
        x_ans+=z[i].w;
        y_ans+=z[i].y;
    }
    x_ans/=n;
    y_ans/=n;
    ans=get(x_ans,y_ans);
   // double timer=clock();
    solve();
    solve();
    solve();
    solve();
   // solve();
    printf("%.3lf %.3lf",x_ans,y_ans);
}

Luogu P2210

#include<bits/stdc++.h>
using namespace std;
int n;
int x,y,w;
int f[103][4];
int pos[1004];
const double T_min=1e-5;
const double delta=0.999;
int GET(){
    int s=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<3;j++){
            s+=abs(pos[i]-pos[f[i][j]]);
        }
    }
    return s;
}
int ans;
void solve(){
    double T=30000;
    while(T>T_min){
        x=rand()%n+1;
        y=rand()%n+1;
    //    while(x==y) y=rand()%n+1;
        swap(pos[x],pos[y]);
        int k=GET();
        if(ans>k){
            ans=k;
        }
        else{
            if(exp((double)(ans-k)/T)<=(double)rand()/INT_MAX){
                swap(pos[x],pos[y]);
            } 
        }
        T*=delta;
    }
}
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=0;j<3;j++){
            cin>>f[i][j];
        }
        pos[i]=i;
    }
    ans=GET();
   // cout<<ans<<endl;
    int timer=clock();
    while(clock()-timer<=CLOCKS_PER_SEC*0.98) solve();
    cout<<ans/2;
}

posted @ 2025-08-08 19:35  Distant_Cloud  阅读(13)  评论(0)    收藏  举报