模拟退火求调
查看原帖
模拟退火求调
1050021
likezheng2023楼主2024/5/30 13:46
#include<bits/stdc++.h>
using namespace std;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}return x*f;}
const int MAXN=1e4+10;
const double EPS=1e-15,DOWN=0.999995;
int n,ans,sum1,sum0,val[MAXN];
bool bit[MAXN];
inline void Sa(){
	double temp=5;
	while(temp>EPS){
		if((double)clock()/CLOCKS_PER_SEC<1.9) return;
		int pos=abs(rand())%n+1;
//		cout<<"当前随机到 "<<pos<<'\n';
//		cout<<"温度 "<<temp<<'\n';
		if(bit[pos]==0){
			int ansnow=abs(sum0-val[pos]-sum1-val[pos]),delta=ansnow-ans;
			double dbdel=(double)delta*1.0;
			if(delta<0){
//				cout<<"当前切换为1更优\n";
				ans=ansnow;
				bit[pos]=1;
				sum0-=val[pos];
				sum1+=val[pos];
			}else if(exp(-dbdel*1.0/temp)*RAND_MAX<rand()){
//				cout<<"以概率接受切换为1\n";
				bit[pos]=1;
				sum0-=val[pos];
				sum1+=val[pos];
			}
		}else{
			int ansnow=abs(sum0+val[pos]-sum1+val[pos]),delta=ansnow-ans;
			double dbdel=(double)delta*1.0;
			if(delta<0){
//				cout<<"当前切换为0更优\n";
				ans=ansnow;
				bit[pos]=0;
				sum0+=val[pos];
				sum1-=val[pos];
			}else if(exp(-dbdel*1.0/temp)*RAND_MAX<rand()){
//				cout<<"以概率接受切换为0\n";
				bit[pos]=0;
				sum0+=val[pos];
				sum1-=val[pos];
			}
		}
		temp*=DOWN;
//		for(int i=1;i<=n;i++) cout<<bit[i]<<" ";
//		cout<<'\n';
	}
}
signed main(){
//	freopen("test.out","w",stdout);
	srand(time(0));
	n=read();
	for(int i=1;i<=n;i++) val[i]=read(),sum0+=val[i],ans+=val[i];
	while((double)clock()/CLOCKS_PER_SEC<1.9) Sa();
	cout<<ans<<'\n';
	return 0;
}
2024/5/30 13:46
加载中...