此片文章主要參考CSDN博主裏頭的一篇文章, 將本身的理解寫下來,以方便後期的查閱。ios
1、C++ 實現算法
1. 已知平面上若干點座標(xi, yi), 求平面上一點p(x, y) , 到這些點的總距離最小。dom
思路: 取全部點的均值爲目標點。計算所有點與目標點求差值的和,將目標點以必定係數朝着總和的方向移動,獲得新的目標點。url
1 // 求最小距離 2 // 限制條件: 1 <= n <= 100, 0<= xi, yi <= 1e4 3 #include<iostream> 4 #include<cstdio> 5 #include<cdtdlib> 6 #include<cmatch> 7 8 using namespace std; 9 10 struct Pt{ 11 double x, y; 12 }P[105] 13 14 double sqr(double x) { 15 return x*x 16 } 17 18 // get distance between two point 19 double dist(Pt a, Pt b) 20 { 21 return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y)); 22 } 23 24 double get_sum(Pt p0, int n) 25 { 26 double ret = 0; 27 for(int i = 0; i < n; ++i) 28 ret += dist(p0, p[i]); 29 30 31 int main 32 { 33 // 設置初始化點數據 34 // p[n] = { ... ,..., ....} 35 // 取全部點的平均位置,做爲最近點的位置 36 double x0=0, y0 =0; 37 for(int i = 0; i < n; ++i) 38 { 39 x0 += p[i].x; 40 y0 += p[i].y; 41 } 42 x0 /= n; 43 y0 /= n; 44 45 double ans = get_sum((pt){x0, y0}, n); // 當前 目標值 46 double temp = le5; // 初始化溫度, 根據須要設定 47 48 while(temp > 0.02) // 0.02 爲溫度的下限, 若溫度爲 temp 達到下限, 則中止搜索 49 { 50 double x = 0, y = 0; 51 for(int i = 0; i < n; ++i) { // 獲取步長的規則根據要求設定 52 x += (p[i].x - x0) / dist((Pt){x0, y0}, p[i]); 53 y += (p[i].x - y0) / dist((Pt){x0, y0}, p[i]); 54 } 55 // 變化後,新的目標值 56 // 此處變化的係數應該是逐漸減少的, temp 逐漸減少,符合要求 57 double tmp = get_sum((Pt){x0 + x * temp, y0 + y * temp}, n); 58 59 // 進行判斷 60 if(temp < ans) 61 { 62 ans = temp; 63 x0 += x * temp; 64 y0 += y * temp; 65 } 66 // 退火算法的精髓 : 當不知足移動條件時, 也按照必定的機率進行移動 67 // 注意 : 移動的機率應該逐漸減少 68 // e n次冪, n 應該小於0 69 // 假設 random() 的做用 : 產生 0- 1 之間的隨機數 70 else if(Math.exp((ans - temp) / temp) > random()) 71 { 72 ans = temp; 73 x0 += x * temp; 74 y0 += y * temp; 75 } 76 temp *= 0.98; // 0.98 爲降火速率(範圍爲0~1, 數字越大,獲得的全局最優解機率越高,運行時間越長) 77 } 78 printf("The minimal dist is : "); 79 printf("%.0f\n", ans); 80 }
2、C# 實現代碼spa
已知空間上若干點(xi, yi, zi), 求空間上包含這些點的最小球半徑 R, 以及球心座標。.net
思路:球心與這些點的最大距離爲半徑, 球心與最大距離點生成向量,將球心朝着該向量方向移動若干距離,再計算半徑的變化。code
1 namespace Test_BST 2 { 3 public class Program 4 { 5 static void Main(string[] args) 6 { 7 // 初始化輸入點 8 List<Point> originPoints = new List<Point>() { ............}; 9 double radius = AnnealAlgorithm(originPoints); 10 } 11 12 private struct Point 13 { 14 public double x; 15 public double y; 16 public double z; 17 } 18 19 // square of a number 20 private static double Sqr(double x) { return x * x; } 21 22 // 兩點之間的距離 23 private static double Dist(Point A, Point B) 24 { 25 return Math.Sqrt(Sqr(A.x - B.x) + Sqr(A.y - B.y) + Sqr(A.z - B.z)); 26 } 27 28 // 求最大半徑 29 private static double GetMaxRadius(Point p0, List<Point> pts) 30 { 31 double maxRadius = 0; 32 foreach (var point in pts) 33 { 34 double radius = Dist(p0, point); 35 maxRadius = radius > maxRadius ? radius : maxRadius; 36 } 37 38 return maxRadius; 39 } 40 41 private static double AnnealAlgorithm(List<Point> originPts) 42 { 43 Point center = new Point(); 44 center.x = 0; 45 center.y = 0; 46 center.z = 0; 47 48 // 將初始化中心點設置爲全部點的代數平均位置 49 foreach (var pt in originPts) 50 { 51 center.x += pt.x; 52 center.y += pt.y; 53 center.z += pt.z; 54 } 55 center.x /= originPts.Count; 56 center.y /= originPts.Count; 57 center.z /= originPts.Count; 58 59 double temp = 1e3; // 初始溫度 60 double coolingFactor = 0.98; // 降溫因子 61 double ans = GetMaxRadius(center, originPts); // 當前最小半徑 62 var random = new Random(); 63 64 while (temp > 1e-5) 65 { 66 Point newCenter = new Point(); 67 double max_r = 0; 68 // 找到與當前中心點距離最遠的點,將中心向着改點移動 69 for (int i = 0; i < originPts.Count; i++) 70 { 71 double r = Dist(center, originPts[i]); 72 if (r > max_r) 73 { 74 newCenter.x = (originPts[i].x - center.x) / r; 75 newCenter.y = (originPts[i].y - center.y) / r; 76 newCenter.z = (originPts[i].z - center.z) / r; 77 max_r = r; 78 } 79 } 80 newCenter.x = center.x + newCenter.x * temp; 81 newCenter.y = center.y + newCenter.y * temp; 82 newCenter.z = center.z + newCenter.z * temp; 83 84 // 移動後的最大半徑 85 double tmp = GetMaxRadius(newCenter, originPts); 86 87 if (tmp < ans) 88 { 89 center.x += newCenter.x * temp; 90 center.y += newCenter.y * temp; 91 center.z += newCenter.z * temp; 92 } 93 else if (Math.Exp((ans -tmp)/temp) > random.NextDouble() ) 94 { 95 center.x += newCenter.x * temp; 96 center.y += newCenter.y * temp; 97 center.z += newCenter.z * temp; 98 } 99 100 temp *= coolingFactor; 101 } 102 double miniRadius = GetMaxRadius(center, originPts); 103 Console.WriteLine("the cooridnate of the center is {0}, the radius value is {1}", center, miniRadius)); 104 105 return miniRadius; 106 } 107 } 108 }
參考: http://blog.csdn.net/whai362/article/details/46980471#commentsblog