96%模拟退火求助
查看原帖
96%模拟退火求助
174806
xbb2楼主2022/8/13 21:43
/*	Name:
	Copyright:[Xcoi]
	Author:xbb2
	Date:
	Description:*/
#include<bits/stdc++.h>
using namespace std;
const int N=60;
const double Max_T=1000;
const double Min_T=0.00000309133584;
const double K=0.998;
int d[N][N],e[N],ans=INT_MAX,n,m,k,r[N],f[N];
int Rand(int x,int y){return rand()%(y-x+1)+x;}
int check(){
	int anss=0;
	for(int i=m+k+1;i<=n;i++){
		int tmp=INT_MAX;
		for(int j=1;j<=m+k;j++)tmp=min(tmp,d[e[i]][e[j]]);
		anss=max(anss,tmp);
	}
	return anss;
}
void SA(){
	for(double T=Max_T;T>=Min_T;T*=K){
		int x=Rand(m+1,m+k),y=Rand(m+k+1,n);
//		printf("%d %d      ",x,y);
		swap(e[x],e[y]);
		int sum=check();double del=ans-sum;
//		printf("%d %lf\n",sum,del);
		if(del>0)ans=sum;
		else if(exp(del/T)*RAND_MAX<=rand())swap(e[x],e[y]);
	}
}
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	srand(309133584);
	cin>>n>>m>>k;
	memset(d,0x3f,sizeof(d));
	for(int i=1;i<=n;i++)d[i][i]=0,e[i]=i;
	for(int i=1;i<=n;i++)scanf("%d",&r[i]),++r[i];
	for(int i=1;i<=n;i++)scanf("%d",&f[i]);
	for(int i=1;i<=n;i++)
		d[i][r[i]]=min(f[i],d[i][r[i]]),d[r[i]][i]=min(f[i],d[i][r[i]]);
	for(int kk=1;kk<=n;kk++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
		d[i][j]=min(d[i][j],d[i][kk]+d[kk][j]);
	for(int i=1;i<=m;i++){
		int x;scanf("%d",&x);++x;
		for(int j=1;j<=n;j++)if(e[j]==x){swap(e[j],e[i]);break;}
	}
//	for(int i=1;i<=n;i++){
//		for(int j=1;j<=n;j++)printf("%10d ",d[i][j]);
//		printf("\n");
//	}
//	for(int i=1;i<=n;i++)printf("[%d]",e[i]);
//	printf("\n");
	if(k==0)ans=check();
	else for(int i=1;i<=100;i++)SA();
	printf("%d",ans);
	return 0;
}

RT

2022/8/13 21:43
加载中...