1. 程式人生 > >雙調歐幾里得旅行商問題(動態規劃) 《java實現》

雙調歐幾里得旅行商問題(動態規劃) 《java實現》

問題描述:

歐幾里得旅行商問題 是對平面上給定的n個點確定一條連線各點的最短閉合旅程的問題。圖a給出了7個點問題的解,這個問題的一般形式是NP完全的,故其解需要多於多項式的時間。

  J.K.Bentley建議通過只考慮雙調旅程來簡化問題,這種旅程即為從最左點開始,嚴格從左到最右點,再嚴格地從最右點回到最左點。圖b顯示了同樣的7個點的問題的最短雙調路線,在這種情況下,多項式的時間的演算法是有可能的。

  描述一個確定最優雙調路線的O(n^2)時間的演算法。可以假設任何兩點的x座標都不相同

解法思路:

            為了方便闡述,我們先對所有點的x進行一個排序,並且標上一個標號0,1,2,3,4,……

          a:資料的提前定義

        首先要理解雙調,也就是說有兩條路線,一個一直向左,一個一直向右,我們不妨設這兩種路線分別為A路線(一直向左),與B路線(一直向右走),那麼我們再來看看A,B都必須滿足什麼條件(A[i]表示從0點到i點路徑,B[j]表示從j點到0點的路徑)

                    1:A,B路線必定沒有重複點,如果有的話也只能是起點和終點

                    2:A,B路線的路徑總和必定是所有情況中最小的

如果滿足這兩個條件那麼此時A+B的路徑和就是我們需要的最優雙調路線。

            小技巧:這裡B[j]是從j到0,並且從j到0和從0到j的路徑沒有變,我們不妨也把B看做另外一條從0一直向右走的路徑(當然這裡的B也同樣需要滿足上面兩個條件)

  為了方便闡述,我們引用d[i][j]表示i點到j點的直線距離(兩點間的距離公式我就不贅述了)

                                s[i][j]表示在A[i],B[j]路徑和最小的情況下的值(當然正如你想的那樣,當i=j,也就是終點,起點都一樣,中間不一樣,就構成了一個環,也就是隻有i個點情況下的最短閉合巡遊路線

     B:動態規劃,公式推導

首先s[0][0]=0;我就不贅述了

 這裡容許我那個不那麼標準的圖,來分析一下(由於對稱的關係,s[i][j]=s[j][i],因此這裡我就只拿一般來就做個圖論,也就是當j>=i時)               ·綜上:

        


            當然i=j可以和j>i+i放在一起,沒有必要把它專門分出來。

    C:程式碼

public class OuJLDTravel {
	
	public static void Print(double map[][]) {
		for(int i=0;i<map.length;i++)
		{
			for(int j=0;j<map[0].length;j++)
			{
				System.out.printf("%.2f ", map[i][j]);
			}
			System.out.println("");
		}
	}
	public static double FindDist(Point p1,Point p2)
	{
		return Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
	}
	public static void main(String[] args) {
		Point[] point = {
			new Point(0, 0),
			new Point(1,6),
			new Point(2,3),
			new Point(5,2),
			new Point(6,5),
			new Point(7,1),
			new Point(8,4)
			};
		double[][] s =  new double[point.length][point.length];
		s[0][0] = 0;
		for(int i=0;i<s.length;i++)
		{
			for(int j=i;j<s[0].length;j++)
			{
				if(i<=j  && i!=j-1 && j!=0)
				{
					s[i][j] = s[i][j-1]+FindDist(point[j-1],point[j]);
					s[j][i] = s[i][j]; 
				}
				else if(i<=j && i==j-1)
				{
					double min = Double.MAX_EXPONENT;
					for(int k=0;k<j;k++)
					{
						if(min>s[i][k]+FindDist(point[k], point[j]))
						{
							min  = s[i][k]+FindDist(point[k], point[j]);
						}
					}
					s[i][j] = min;
					s[j][i] = min;
				}
			}
		}
		Print(s);
	}

}
class Point{
	public int x;
	public int y;
	public Point(int x,int y) {
		this.x = x;
		this.y = y;
		// TODO Auto-generated constructor stub
	}
	public Point() {
		// TODO Auto-generated constructor stub
	}
}