题目描述 Description
有 N ( <=20 ) 台 PC 放在机房内,现在要求由你选定一台 PC,用共 N-1 条网线从这台机器开始一台接一台地依次连接他们,最后接到哪个以及连接的顺序也是由你选定的,为了节省材料,网线都拉直。求最少需要一次性购买多长的网线。(说白了,就是找出 N 的一个排列 P1 P2 P3 ..PN 然后 P1 -> P2 -> P3 -> ... -> PN 找出 |P1P2|+|P2P3|+...+|PN-1PN| 长度的最小值)
输入描述 Input Description
第一行 N ,下面 N 行,每行分别为机器的坐标(x,y) ( 实数 -100<=x,y<=100 )
输出描述 Output Description
最小的长度,保留两位小数。
样例输入 Sample Input
3
0 0
1 1
1 -1
样例输出 Sample Output
2.83
此题使用模拟退火算法做
对于刚刚看模拟褪火算法 我还以为是模拟呢
╮( ̄▽ ̄")╭ 竟然是一种基于启发式搜索的算法
随机化初始状态 每次可以得出一个局部最优解
先粘一段百度百科
模拟退火算法来源于固体退火原理,是一种基于概率的算法,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。
算法简介
编辑模拟退火算法(Simulated Annealing,SA)最早的思想是由N. Metropolis[1] 等人于1953年提出。1983 年,S. Kirkpatrick 等成功地将退火思想引入到组合优化领域。它是基于Monte-Carlo迭代求解策略的一种随机寻优算法,其出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法从某一较高初温出发,伴随温度参数的不断下降,结合概率突跳特性在解空间中随机寻找目标函数的全局最优解,即在局部最优解能概率性地跳出并最终趋于全局最优。模拟退火算法是一种通用的优化算法,理论上算法具有概率的全局优化性能,目前已在工程中得到了广泛应用,诸如VLSI、生产调度、控制工程、机器学习、神经网络、信号处理等领域。
模拟退火算法是通过赋予搜索过程一种时变且最终趋于零的概率突跳性,从而可有效避免陷入局部极小并最终趋于全局最优的串行结构的优化算法。
随机生产一种情况 对此进行优化 最后得出一个结果
重复多次 得出结论(该结论不一定最优 但重复次数越多 答案越优)
随机生产一种情况 对此进行优化 最后得出一个结果
重复多次 得出结论(该结论不一定最优 但重复次数越多 答案越优)
#include<iostream> #include<stdio.h> #include<math.h> #include<stdlib.h> #include<algorithm> using namespace std; int n,x[25],y[25],id[25]; double f[25][25],ans=1000000.0; void swapid(int a,int b) { for(int i=a,j=b;i<=j;i++,j--) swap(id[i],id[j]); } double get() { double s=0; for(int i=0;i<100;i++) swap(id[rand()%n+1],id[rand()%n+1]); for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) if(f[id[i-1]][id[i]]+f[id[j]][id[j+1]]>f[id[i-1]][id[j]]+f[id[i]][id[j+1]]) swapid(i,j); for(int i=1;i<n;i++) s+=f[id[i]][id[i+1]]; return s; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]); for(int i=0;i<=n;i++) id[i]=i; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); for(int i=0;i<2000;i++) ans=min(ans,get()); printf("%.2f ",ans); return 0; }