程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 1347 - Tour (雙調歐幾裡得旅行商問題)

1347 - Tour (雙調歐幾裡得旅行商問題)

編輯:C++入門知識

鏈接:1347 - Tour

沒想通,看了題解,學習了。。。

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

J.L. Bentley 建議通過只考慮雙調旅程(bitonic tour)來簡化問題,這種旅程即為從最左點開始,嚴格地從左到右直至最右點,然後嚴格地從右到左直至出發點。下圖(b)顯示了同樣的7個點的最短雙調路線。在這種情況下,多項式的算法是可能的。事實上,存在確定的最優雙調路線的O(n*n)時間的算法。

\ 圖a \ 圖b<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+16I61NrSu7j2taXOu9WkJiMyNjY4NDvJz8/Uyr61xMa9w+bJz7XExt+49rXjoaMgYSnX7rbMsdW6z8K3z98ss6S2yLTz1LzKxzI0Ljg5oaPV4rj2wrfP37K7ysfLq7X3tcSho2Ipz+DNrLXjtcS8r7rPyc+1xNfutszLq7X3sdW6z8K3z9+ho7Oktsi089S8yscyNS41OKGjPC9wPgo8cD7V4srH0ru49svjtbzJz7XEy7y/vMziMTUtMaGjPC9wPgo8cD7K18/Ivau4+LP2tcS148XF0PKjrLnYvPzX1nijrNbY0MKx4LrFo6y009fz1sHT0jGjrDKjrDOjrKGto6xuoaM8L3A+CjxwPrao0uVwW2ldW2pdo6yx7cq+veG142m1vb3hteNq1q685LXEvuDA66GjPC9wPgo8cD62qNLlZFtpXVtqXaOsse3KvrTTacGstb0xo6zU2bTTMcGstb1qo6yjqNei0uKjrGk+aqOsx9KyosO709DP4MGsoaOjqTwvcD4KPHA+PGltZyBzcmM9"http://www.2cto.com/uploadfile/Collfiles/20140323/20140323091259196.png" alt="\">

對於任意一個點i來說,有兩種連接方法,一種是如圖(a)所示,i與i-1相連,另一種呢是如圖(b),i與i-1不相連。

根據雙調旅程,我們知道結點n一定與n相連,那麼,如果我們求的d[n][n-1],只需將其加上p[n-1][n]就是最短雙調閉合路線。

根據上圖,很容易寫出方程式:

dp[i][j]=dp[i-1][j]+dist[i][i-1];

dp[i][i-1]=min(dp[i][i-1],dp[i-1][j]+dist[j][i]);


代碼:

#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define min(a,b) ((a)<(b)?(a):(b))

const int N = 105;
int n, i, j;
double x[N], y[N], dp[N][N];

double dis(int v1, int v2) {
	return sqrt((x[v1] -  x[v2]) * (x[v1] -  x[v2]) + (y[v1] -  y[v2]) * (y[v1] -  y[v2]));
}

int main() {
	while (~scanf("%d", &n)) {
		double ans = INF;
		for (i = 1; i <= n; i++)
			scanf("%lf%lf", &x[i], &y[i]);
		dp[2][1] = dis(2, 1);
		for (i = 3; i <= n; i++) {
			dp[i][i - 1] = INF;
			for (j = 1; j < i - 1; j++) {
				dp[i][j] = dp[i - 1][j] + dis(i, i - 1);
				dp[i][i - 1] = min(dp[i][i - 1], dp[i - 1][j] + dis(j, i));
				if (i == n) ans = min(ans, dp[i][j] + dis(j, i));
			}
		}
		printf("%.2lf\n", min(ans, dp[n][n - 1] + dis(n - 1, n)));
	}
	return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved