简单退火 萌新求hack
查看原帖
简单退火 萌新求hack
50690
蒻得不行楼主2020/10/6 00:11
#include<bits/stdc++.h>
using namespace std;
int a[15],b[15],t,n,h1,h2,i,T; //将两边金币分开存储 
long long now;
void sa()
{
   double t=3000;
   while (t>1e-15)
   {
      int ex=rand()%h1,ey=rand()%h2;// 随机取位置 
      long long ew=now-2*a[ex]+2*b[ey];//差值更新 
      int de=abs(ew)-abs(now);
      if (de<0)
      {
         swap(a[ex],b[ey]);//交换 
         now=ew;
      }
      else if(exp(-de/t)*RAND_MAX>rand()) //接受更差的答案 
      {
		swap(a[ex],b[ey]);
		now=ew;
      }
      t*=0.997;
   }
}
int main(){
	srand(time(NULL));
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		if(n==1){//特判,不然会re 
			scanf("%d",&now);
			printf("%d\n",now);
			continue;
		}
		h1=n/2;//前一半金币数 
		h2=(n+1)/2;//后一半 
		now=0;//差值 
		for(i=0;i<h1;i++) scanf("%d",&a[i]),now+=a[i];//读入时顺便计算差值 
		for(i=0;i<h2;i++) scanf("%d",&b[i]),now-=b[i];
		sa();
		sa();
		sa();
		sa();sa();
		sa();
		sa();
		sa();sa();
		sa();
		sa();
		printf("%lld\n",abs(now));
	}
	return 0;
}

2020/10/6 00:11
加载中...