模拟退火的答案比正确答案更优?
查看原帖
模拟退火的答案比正确答案更优?
804607
rainygame楼主2023/11/4 11:03

萌新初学模拟退火,求调。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const double d(0.97);
mt19937 rnd(time(0));

int t, n, s1, s2, mid, ans;
int v[31];

int f(int l, int r){
    return rnd() % (r-l+1) + l + 1;
}

double g(){
    return (double)rnd() / UINT_MAX;
}

void change(int x, int y){
    s1 = s1-v[x]+v[y];
    s2 = s2-v[y]+v[x];
    swap(v[x], v[y]);
}

void SA(){
    double t(1e5);
    while (t > 1e-5){
        int x(f(1, mid)), y(f(mid+1, n));
        int dis(llabs(s1-s2+((v[y]-v[x])<<1)));
        double delta(dis-ans);
        if (delta < 0){
            ans = dis;
            change(x, y);
        }else if (exp(-delta/t) > g()) change(x, y);
        t *= d;
    }
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> t;
    while (t--){
        cin >> n;
        s1 = s2 = 0;
        mid = n >> 1;
        for (int i(1); i<=n; ++i){
            cin >> v[i];
            if (i <= mid) s1 += v[i];
            else s2 += v[i];
        }
        // cout << s1 << ' ' << s2 << '\n';
        // return 0;
        if (n == 1){
            cout << v[1] << '\n';
            continue;
        }

        ans = abs(s1-s2);
        for (int i(1); i<=200; ++i) SA();
        cout << ans << '\n';
    }

    return 0;
}

2023/11/4 11:03
加载中...