模拟退火求调
查看原帖
模拟退火求调
637073
wujingfey楼主2023/11/15 15:59

被爆金币了,后面 4 个点 RE,数组都开到 3000 了,前面几个点的错误率也挺高的。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3005;
const double eps=1e-8,down=0.9112;
int T,n,s1,s2,ans;
int a[N],a1[N],a2[N];
int get(){
	int sum1=0,sum2=0;
	for(int i=1;i<=s1;i++)
		sum1+=a1[i];
	for(int i=1;i<=s2;i++)
		sum2+=a2[i];
	return abs(sum1-sum2);
}
void SA(){
	double temp=50000;
	while(temp>eps){
		int x=rand()%s1+1;
		int y=rand()%s2+1;
		swap(a1[x],a2[y]);
		int dif=get();
		if(dif<ans){
			ans=dif;
			temp*=down;
			continue;
		}else if(exp(-dif/temp)*RAND_MAX>rand()){
			temp*=down;
			continue;
		}
		temp*=down;
		swap(a1[x],a2[y]);//换回来 
	}
}
signed main(){
	srand(time(0));
	cin>>T;
	while(T--){
		memset(a,0,sizeof(a));
		memset(a1,0,sizeof(a1));
		memset(a2,0,sizeof(a2));
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		s1=n/2,s2=n-s1,ans=1e18+7;
		for(int i=1;i<=s1;i++) a1[i]=a[i]; 
		for(int i=1;i<=s2;i++) a2[i]=a[i+s1];
		int t=50;
		while(t--) SA();
		cout<<ans<<'\n';
	}
	return 0;
}
2023/11/15 15:59
加载中...