The sol to coin(SA)

The sol to coin(SA)

https://www.luogu.com.cn/problem/P3878

这题是模拟退火的板子。

虽然一般的模拟退火不能支持多测的题目,因为时间可能卡不好,但在没有办法的办法下(其实就是乱搞),可以自己酌情设置SA的参数和SA的次数。

AC_code

#include<random>
#include<algorithm>
#define Ying using
#define AK namespace
#define IOI std;
#define By return
#define JX_JOKER 0;
#define int long long
#define FOR(i,_l,_r) for(int i=(_l);i<=(_r);i++)
#define il inline
Ying AK IOI
il int read(){
    int x=0,f=1;char c=getchar_unlocked();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;
        c=getchar_unlocked();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';
        c=getchar_unlocked();
    }
    return x*f;
}
il void print(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
const int N=35;
int a[N];
int l[N];int r[N];
int T;
int n;
int s1;
int s2;
int dis;
int ans;
void SA(){
    srand(20090404);
    double T_begin=2009.0404,T_end=1e-15;
    for(;T_begin>=T_end;T_begin*=0.951){
        int p=rand()%(n/2)+1;
        int q=rand()%(n/2)+1;
        int st=dis;
        int S1=s1;
        int S2=s2;
        s1=s1-l[p]+r[q];
        s2=s2-r[q]+l[p];
        swap(l[p],r[q]);
        dis=abs(s1-s2);
        if(dis<ans) ans=dis;
        else if(exp(-(dis-ans)/T_begin)*RAND_MAX<rand()){
            swap(l[p],r[q]);
            dis=st;s1=S1;s2=S2;
        }
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
    freopen("coin.in","r",stdin);
    freopen("coin.out","w",stdout);
    #endif
    T=read();
    while(T--){
        s1=0;s2=0;
        n=read();
        FOR(i,1,n) a[i]=read();
        if(n&1) a[++n]=0;
        //sort(a+1,a+n+1);
        FOR(i,1,n/2) l[i]=a[i];
        FOR(i,1,n/2) s1+=l[i];
        FOR(i,1,n/2) r[i]=a[i+n/2];
        FOR(i,1,n/2) s2+=r[i];
        dis=abs(s1-s2);
        ans=dis;
        FOR(i,1,600) SA();
        print(ans);puts("");
    }
    By JX_JOKER
}
posted @ 2024-10-24 13:34  Qian·JXのjoker  阅读(4)  评论(0编辑  收藏  举报