题解 P1248 【加工生产调度】

luogu

思路

模拟退火板子题
用模拟退火打乱顺序再计算即可
(话说luogu都没人用模拟退火吗?看来是都不屑骗分)

Code

#include<bits/stdc++.h>
using namespace std;
int n,A[10010],B[10010],Q[10010],ansq[10010],ans=0x7FFFFFFF,cs;
int calc()
{
	int nowA=0,nowB=0;
	for(int i=1;i<=n;i++)
	{
		nowA+=A[Q[i]];
		if(nowB<nowA)
		{
			nowB=nowA;
		}
		nowB+=B[Q[i]];
	}
	return nowB;
}
int check()
{
	for(int i=1;i<=n;i++)
	{
		if(ansq[i]<Q[i])
		{
			return 0;
		}
		if(Q[i]<ansq[i])
		{
			return 1;
		}
	}
}
double T;
double eps=1e-4;
double xs=0.999;
void SA()
{
	T=10000;
	while(T>eps)
	{
		int x=rand()%n+1;
		int y=rand()%n+1;
		swap(Q[x],Q[y]);
		int now=calc();
		int Delta=now-ans;
		if(Delta<0||Delta==0&&check())
		{
			ans=now;
			for(int i=1;i<=n;i++)
			{
				ansq[i]=Q[i];
			}
		}
		else
		{
			if(exp(Delta)<(double)(rand()*T))
			{
				swap(Q[x],Q[y]);
			}
		}
		T*=xs;
		cs++;
	} 
}
void work()
{
	for(int i=1;i<=10;i++)
	{
		SA();
	}
}
int main()
{
	srand(time(NULL));srand(rand());srand(rand());
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>A[i];
		Q[i]=i;
	}
	for(int i=1;i<=n;i++)
	{
		cin>>B[i];
	}
	work();
	cout<<ans<<endl;
	for(int i=1;i<=n;i++)
	{
		cout<<ansq[i]<<" ";
	}
} 
posted @ 2019-07-29 19:13  G_A_TS  阅读(371)  评论(0编辑  收藏  举报