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