萌新初学模拟退火,求调。
#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;
}