题解 P1248 【加工生产调度】
思路
模拟退火板子题
用模拟退火打乱顺序再计算即可
(话说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]<<" ";
}
}