模拟退火能不能过这道题呀
  • 板块P2123 皇后游戏
  • 楼主Lqwq
  • 当前回复8
  • 已保存回复8
  • 发布时间2021/11/8 19:37
  • 上次更新2023/11/4 01:05:11
查看原帖
模拟退火能不能过这道题呀
327069
Lqwq楼主2021/11/8 19:37

蒟蒻写的模拟退火感觉虽然乱七八糟但是希望试一试,求大佬指点

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;

int t,n,c[50005],c1[50005],s,s1,ans;

struct lwt
{
	int a;
	int b;
}game[50005],game1[50005];

bool cmp(lwt a,lwt b)
{
	return a.a<b.a;
}

bool cmp1(lwt a,lwt b)
{
	return a.b<b.b;
}

void sa();
int get();

int main()
{	
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;++i)
		{
			cin>>game[i].a>>game[i].b;
			game1[i].a=game[i].a;
			game1[i].b=game[i].b;
		}
		sort(game+1,game+n+1,cmp);
		sort(game1+1,game1+n+1,cmp1);
		memset(c,0,sizeof(c));
		memset(c1,0,sizeof(c1));
		s=0;
		s1=0;
		for(int i=1;i<=n;++i)
		{
			s+=game[i].a;
			c[i]+=max(c[i-1],s)+game[i].b;
		}
		for(int i=1;i<=n;++i)
		{
			s1+=game1[i].a;
			c1[i]+=max(c1[i-1],s)+game1[i].b;
		}
		int ans=min(c[n],c1[n]);
		int ctrl=275;
		while(ctrl--)
		sa();
		printf("%d\n",ans);
	}
	
	return 0;
}

int get()
{
	s=0;
	s1=0;
	memset(c,0,sizeof(c));
	memset(c1,0,sizeof(c1));
	for(int i=1;i<=n;++i)
	{
		s+=game[i].a;
		c[i]+=max(c[i-1],s)+game[i].b;
	}
	for(int i=1;i<=n;++i)
	{
		s1+=game1[i].a;
		c1[i]+=max(c1[i-1],s)+game1[i].b;
	}
	return min(c[n],c1[n]);
}

void sa()
{
	double begin1=5000,end1=2e-10,change1=0.7112;
	for(double i=begin1;i>end1;i*=change1)
	{
		int x=rand()%n+1,y=rand()%n+1;
		swap(game[x].a,game1[y].a);
		swap(game[x].b,game1[y].b);
		int sum=get();
		if(sum<ans)
		ans=sum;
		else
		{
			if(exp((ans-sum)/i)<(double(rand())/RAND_MAX))
			swap(game[x].a,game1[y].a);
			swap(game[x].b,game1[y].b);
		}
	}
}
2021/11/8 19:37
加载中...