標籤:style blog http os io strong for 2014
解題思路:①首先把橫座標x排序,大約用時O(nlgn),用堆排序或者歸併排序都能達到此效果。提示既然是從左至右掃描,那麼x座標從左至右是按照遞增順序掃描。
②子結構:在按照①已排好序的基礎上,才能進行這步操作,注意排序過程這裡已省略。下面定義b[i][j]=從左邊第1個點到第i個點的距離+從左邊第1個點到第j個點的距離,並且兩條路徑上必須經過各不相同的所有1到i到j之間所有點。用distance(T,i,j)=|pipj|表示從第i個點到第j個點的直線距離。
③歸納的遞迴公式如下:
代碼如下:
#include <iostream>#include <math.h>using namespace std;#define n 7struct Coordinate{double x;double y;}T[n];//計算點i和點j之間的直線距離 double distance(Coordinate T[],int i,int j) { return sqrt((T[i].x - T[j].x) * (T[i].x - T[j].x) + (T[i].y - T[j].y) * (T[i].y - T[j].y)); } double Bitonic_euclidean_traveling_salesman_problem(struct Coordinate T[]){//雙調歐幾裡得旅行商問題double b[n+1][n+1]={0};//記錄最短路徑的長度 //計算所有情況下的b[i][j],1 <= i <= j b[1][2] = distance(T,1,2);//初始化 for ( int j=3;j<=n;j++) { //i < j-1 for (int i=1;i<=j-2;i++) { b[i][j]=b[i][j-1]+distance(T,j-1,j); } //i = j - 1,b[i][j] = min(b[k][j - 1] + distance(k,j)); b[j-1][j]=0x7fffffff; for (int k=1;k<=j-2;k++) { double q=b[k][j-1]+distance(T,k,j); if (q<b[j-1][j]) { b[j-1][j]=q; } } }b[n][n]=b[n-1][n]+distance(T,n-1,n);return b[n][n];}void main(){ struct Coordinate T[n+1]={0}; for( int i = 1; i <=n; i++) cin>>T[i].x>>T[i].y; cout<<Bitonic_euclidean_traveling_salesman_problem(T)<<endl;}
範例輸出:
總結:此程式已耗用時間為O(n2),這裡的痛點主要在歸納遞推公式上(i<j-1與i=j-1兩種情況需要反覆思考才可能得出結論),其次才是具體實現。