Haywire

还是模拟退火乱搞。
不过考虑记录一下在整个退火过程中的最优答案。
而不是只看最后剩下的解。
退火是一个随机算法,他有很大的几率能跳到最优解,但也很有可能从最优解跳出去。
所以要记录答案。

Haywire
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define ll long long
#define N 20

ll n;

ll to[N][10];
ll ans[N];

inline ll find(){
	ll ansi = 0;
	for(int i = 1;i <= n;++i)
	for(int j = 1;j <= 3;++j)
	ansi += std::abs(ans[i] - ans[to[i][j]]);
	return ansi / 2;
}

ll fans = 0x3f3f3f3f;

inline void sa(){
	double T = 20000;
	double eps = 1e-15;
	while(T > eps){
		int x,y;
		do{
		x = rand() % n + 1;
		y = rand() % n + 1;
		}while(x == y);
//		std::cout<<x<<" "<<y<<std::endl;
		ll z = -find();
		fans = std::min(fans,-z);
		std::swap(ans[x],ans[y]);
		z = z + find();
		if(z > 0 && exp(-z / T) * RAND_MAX < rand())
		std::swap(ans[x],ans[y]);
		T *= 0.996;
	}
}

int main(){
	scanf("%lld",&n);
	for(int i = 1;i <= n;++i)
	for(int j = 1;j <= 3;++j)
	scanf("%lld",&to[i][j]);
	for(int i = 1;i <= n;++i)
	ans[i] = i;
	for(int i = 1;i <= 127;++i)
	sa();
	std::cout<<fans<<std::endl; 
}
posted @ 2021-05-13 12:13  fhq_treap  阅读(136)  评论(0编辑  收藏  举报