標籤:動態規劃 acm 雙調歐幾裡得旅行商問題
Tour
| Time Limit: 1000MS |
|
Memory Limit: 65536K |
| Total Submissions: 3585 |
|
Accepted: 1597 |
Description
John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts visiting beautiful places. To save money, John must determine the shortest closed tour that connects his destinations. Each destination is represented by a point in the plane pi = < xi,yi >. John uses the following strategy: he starts from the leftmost point, then he goes strictly left to right to the rightmost point, and then he goes strictly right back to the starting point. It is known that the points have distinct x-coordinates.
Write a program that, given a set of n points in the plane, computes the shortest closed tour that connects the points according to John‘s strategy.
Input
The program input is from a text file. Each data set in the file stands for a particular set of points. For each set of points the data set contains the number of points, and the point coordinates in ascending order of the x coordinate. White spaces can occur freely in input. The input data are correct.
Output
For each set of data, your program should print the result to the standard output from the beginning of a line. The tour length, a floating-point number with two fractional digits, represents the result. An input/output sample is in the table below. Here there are two data sets. The first one contains 3 points specified by their x and y coordinates. The second point, for example, has the x coordinate 2, and the y coordinate 3. The result for each data set is the tour length, (6.47 for the first data set in the given example).
Sample Input
31 12 33 141 12 33 14 2
Sample Output
6.477.89
Source
Southeastern Europe 2005
解題思路:
轉載於:http://blog.sina.com.cn/s/blog_51cea4040100gkcq.html
歐幾裡得旅行商問題是對平面上給定的n個點確定一條串連各點的最短閉合旅程的問題。(a)給出了一個7個點問題的解。這個問題的一般形式是NP完全的,故其解需要多於多項式的時間。
J.L. Bentley 建議通過只考慮雙調旅程(bitonic tour)來簡化問題,這種旅程即為從最左點開始,嚴格地從左至右直至最右點,然後嚴格地從右至左直至出發點。(b)顯示了同樣的7個點的最短雙調路線。在這種情況下,多項式的演算法是可能的。事實上,存在確定的最優雙調路線的O(n*n)時間的演算法。
注:在一個單位柵格上顯示的平面上的七個點。 a)最短閉合路線,長度大約是24.89。這個路線不是雙調的。b)相同點的集合上的最短雙調閉合路線。長度大約是25.58。
這是一個算導上的思考題15-1。
首先將給出的點排序,關鍵字x,重新編號,從左至右1,2,3,…,n。
定義p[i][j],表示結點i到結點j之間的距離。
定義d[i][j],表示從i連到1,再從1連到j,(注意,i>j,且並沒有相連。)
對於任意一個點i來說,有兩種串連方法,一種是(a)所示,i與i-1相連,另一種呢是(b),i與i-1不相連。
根據雙調旅程,我們知道結點n一定與n相連,那麼,如果我們求的d[n][n-1],只需將其加上p[n-1][n]就是最短雙調閉合路線。
根據,很容易寫出方程式:
d[i][j]=d[i-1][j]+p[i][i-1];
d[i][i-1]=min(d[i-1][j]+p[j][i]);
總結一下這種題目解題步驟:
1. 明確所有的點
2. 求出任意兩點之間的距離,可以寫一個單獨的函數,隨時調用,也可以預先處理,這個“距離”根據題目的不同有不同的意思.
3. 對這些點按x座標從小到大進行排序
4. 使用雙調歐幾裡得旅行商問題的演算法
代碼:
#include <iostream>#include <cmath>#include <iomanip>#include <algorithm>#include <string.h>using namespace std;const int inf=0x7fffffff;const int maxn=1000;int n;//n個點double dp[maxn][maxn];struct P{ double x,y;}point[maxn];bool cmp(P a,P b){ if(a.x<b.x) return true; return false;}double dis(P a,P b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double DP(int n)//雙調歐幾裡得旅行商問題演算法,dp[n][n]為所求{ sort(point+1,point+1+n,cmp); dp[1][2]=dis(point[1],point[2]); for(int j=3;j<=n;j++) { for(int i=1;i<=j-2;i++) dp[i][j]=dp[i][j-1]+dis(point[j-1],point[j]); dp[j-1][j]=inf; for(int k=1;k<=j-2;k++) { double temp=dp[k][j-1]+dis(point[k],point[j]); if(temp<dp[j-1][j]) dp[j-1][j]=temp; } } dp[n][n]=dp[n-1][n]+dis(point[n-1],point[n]); return dp[n][n];}int main(){ while(cin>>n) { for(int i=1;i<=n;i++) cin>>point[i].x>>point[i].y; cout<<setiosflags(ios::fixed)<<setprecision(2)<<DP(n)<<endl; } return 0;}