求问
  • 板块灌水区
  • 楼主Ac_forever
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/1/28 07:50
  • 上次更新2024/1/28 10:30:10
查看原帖
求问
768416
Ac_forever楼主2024/1/28 07:50

ATcoder ABC 338 D: 这是一份模拟退火的代码:

#include<cmath>
#include<ctime>
#include<cstdio>
#include<climits>
#include<iostream>
#define N 200001
using namespace std;
int n,m,a[N];
typedef long long ll;
ll ans=2147483647;
double eps=1e-4;
ll p(ll x){
	if(x<1)return 1;
	if(x>n)return n;
	return x;
}
ll calc(ll x){
	ll ans=0;
	for(int i=2;i<=m;i++){
		if(x>min(a[i-1],a[i])&&x<max(a[i],a[i-1]))ans+=abs(n-max(a[i],a[i-1]))+min(a[i],a[i-1]);
		else ans+=abs(a[i]-a[i-1]);
	}
	return ans;
}
int RND(){
	return 2*rand()-RAND_MAX;
}
void solve(){
	double T=1e6;
	ll x=rand()%n+1;
	ll now=calc(x);
	ans=min(ans,now);
	while(T>eps){
		ll y=p(x+(ll)(T*RND())%(n+1ll));
		ll qq=calc(y);
		double delta=qq-now;
		if(qq<ans)ans=qq;
		if(now<qq||exp(-delta/T)*RAND_MAX>rand())x=y,now=qq;//,printf("%d %d\n",x,now)
		T*=0.985;
	}
}
int main(){
	srand(19260817);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d",&a[i]);
	while((double)clock()/CLOCKS_PER_SEC<1.7)solve();
	printf("%lld",ans);
}

对于这个数据:

163054 10
62874 19143 77750 111403 29327 56303 6659 18896 64175 26369

他输出388911

而当把注释掉那部分代码写到 now=qq后面,如下:


if(now<qq||exp(-delta/T)*RAND_MAX>rand())x=y,now=qq,printf("%d %d\n",x,now);

即对于每一次转移都进行观测,那么输出就会变成390009

就离谱,为什么?波粒二象性?

2024/1/28 07:50
加载中...