为什么使用模拟退火排序正确率如此低
查看原帖
为什么使用模拟退火排序正确率如此低
803885
_8008008楼主2024/10/13 14:00

是不是我写错了(
原理是计算后一个数比前一个数小的个数,对该函数进行退火。

#include<iostream>
#include<random>
#include<ctime>
#include<cmath>
#define double long double
using namespace std;
int n,w,a[100001];
mt19937 mt(time(NULL));
int rd(int l,int r){
	int add=mt()%(r-l+1);
	return l+add;
}
int count(int x,int y){
	int ans=0;
	if(x>y)swap(x,y);
	if(y==x+1){
		if(a[x]>a[y])ans--;
		if(a[x]<a[y])ans++;
		if(x>1)ans-=a[x-1]>a[x];
		if(y<n)ans-=a[y]>a[y+1];
		if(x>1)ans+=a[x-1]>a[y];
		if(y<n)ans+=a[x]>a[y+1];
	}else{
		if(x>1)ans-=a[x-1]>a[x];
		if(x<n)ans-=a[x]>a[x+1];
		if(y>1)ans-=a[y-1]>a[y];
		if(y<n)ans-=a[y]>a[y+1];
		if(x>1)ans+=a[x-1]>a[y];
		if(x<n)ans+=a[y]>a[x+1];
		if(y>1)ans+=a[y-1]>a[x];
		if(y<n)ans+=a[x]>a[y+1];
	}
	return ans;
}
void SA(){
	double temp=1e10;
	while(temp>1e-8){
		int s1=rd(1,n),s2=rd(1,n);
		while(s1==s2)s2=rd(1,n);
		int delta=count(s1,s2);
		if(w+delta==0){
			swap(a[s1],a[s2]);
			for(int i=1;i<=n;i++){
				printf("%d ",a[i]);
			}
			exit(0);
		} 
		if(delta<0){
			swap(a[s1],a[s2]);
			w+=delta;
		}else{
			if(exp(-delta/temp)*1e9>=rd(1,1e9)){
				swap(a[s1],a[s2]);
				w+=delta;
			}
		}
		temp*=0.995;
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for(int i=2;i<=n;i++){
		w+=a[i-1]>a[i];
	}
	while(true)SA();
	return 0;
}
2024/10/13 14:00
加载中...