P3878 [TJOI2010]分金币
题目链接
题意分析
这道题正解好像是折半状压 但是俺就是喜欢模拟退火
每一次随机的话 就是交换两个数的位置 然后比较前一半和后一半
CODE:
#include<bits/stdc++.h>
#define INF 0x7fffffff
#define N 2010
using namespace std;
int T,n;
long long ans;
long long num[N];
long long getans()
{
long long sum1=0,sum2=0;
int mid=(1+n)>>1;
for(int i=1;i<=mid;++i) sum1+=num[i];
for(int i=mid+1;i<=n;++i) sum2+=num[i];
return abs(sum1-sum2);
}
void SA()
{
for(double Te=3872;Te>1e-10;Te*=0.972)
{
int x=rand()%n+1,y=rand()%n+1;
swap(num[x],num[y]);
long long tmp=getans();
if(tmp<ans) ans=tmp;
else if(exp((double)(ans-tmp)/Te)*RAND_MAX<(double)rand()) swap(num[x],num[y]);
}
}
int main()
{
srand(19260817+998244353);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%lld",&num[i]);
ans=INF;
for(int x=1;x<=1000;++x) SA();
printf("%lld\n",ans);
}
return 0;
}