21476: Car的旅行路線
時間限制: 1 Sec 記憶體限制: 128 MB
送出: 2 解決: 1
[送出][狀态][讨論版][命題人:外部導入]
題目描述
又到暑假了,住在城市A的Car想和朋友一起去城市B旅遊。她知道每個城市都有四個飛機場,分别位于一個矩形的四個頂點上,同一個城市中兩個機場之間有一 條筆直的高速鐵路,第I個城市中高速鐵路了的機關裡程價格為Ti,任意兩個不同城市的機場之間均有航線,所有航線機關裡程的價格均為t。
那麼Car應如何安排到城市B的路線才能盡可能的節省花費呢?她發現這并不是一個簡單的問題,于是她來向你請教。
找出一條從城市A到B的旅遊路線,出發和到達城市中的機場可以任意選取,要求總的花費最少。
輸入
第一行有四個正整數s,t,A,B。
S表示城市的個數,t表示飛機機關裡程的價格,A,B分别為城市A,B的序号,(1<=A,B<=S)。
接下來有S行,其中第I行均有7個正整數xi1,yi1,xi2,yi2,xi3,yi3,Ti,這當中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I個城市中任意三個機場的坐标,T I為第I個城市高速鐵路機關裡程的價格。
資料規模和約定
0
輸出
共有n行,每行一個資料對應測試資料,保留一位小數。
樣例輸入
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3
樣例輸出
47.5
對于s個城市,每個城市4個機場,視為4*s個結點,這4*s個節點構成了一個圖,轉變為求最短路徑問題,采用Dijkstra方法。邊存儲每個城市的機場資訊,邊計算各機場間距離和費用并存入鄰接表中。整體思路不複雜,但實作起來很麻煩,很容易出錯,比如在存儲的格式、計算距離、存儲鄰接表等細節上。
代碼
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXV = ;
const double INF = ;
int s, t, A, B;
struct node{ //用于存儲機場坐标,友善計算距離
int x, y;
};
struct airport{ //對s個城市,每個城市的機場布局存于該結構體中。s内有四個元素
vector<node> s;
int T;
};
struct NODE{ //用于存在鄰接表的結構體
int v;
double dis;
};
vector<NODE> Adj[MAXV]; //鄰接表
vector<airport> airp; //存儲s個城市的機場資訊
double d[MAXV]; //最短距離
bool vis[MAXV] = {false};
node findLastPoint(node s1, node s2, node s3){ //給出矩形的三個頂點坐标,求第四個頂點坐标
if((s2.x - s1.x) * (s3.x- s1.x) + (s2.y - s1.y) * (s3.y- s1.y) == ){
node tmp;
tmp.x = s2.x + s3.x - s1.x;
tmp.y = s2.y + s3.y - s1.y;
return tmp;
}else if((s1.x - s2.x) * (s3.x- s2.x) + (s1.y - s2.y) * (s3.y- s2.y) == ){
node tmp;
tmp.x = s1.x + s3.x - s2.x;
tmp.y = s1.y + s3.y - s2.y;
return tmp;
}else{
node tmp;
tmp.x = s1.x + s2.x - s3.x;
tmp.y = s1.y + s2.y - s3.y;
return tmp;
}
}
double D(node s1, node s2){ //求兩坐标s1和s2的距離
double d = sqrt((s1.x - s2.x) * (s1.x - s2.x) + (s1.y - s2.y) * (s1.y - s2.y));
return d;
}
double MIN(double a, double b, double c, double d) { //四個距離中的最小值
double tmp;
if(a < b){
tmp = a;
}else{
tmp = b;
}
if(c < tmp){
tmp = c;
}
if(d < tmp){
tmp = d;
}
return tmp;
}
void Dijkstra(int a){
fill(d, d + MAXV, INF);
fill(vis, vis + MAXV, false);
d[a] = ;
for(int i = ; i < s*; i++) {
int u = -;
double MIN = INF;
for(int j = ; j < s*; j++) {
if(vis[j] == false && d[j] < MIN) {
u = j;
MIN = d[j];
}
}
if(u == -) return;
vis[u] = true;
for(int j = ; j < Adj[u].size(); j++) {
int v = Adj[u][j].v;
if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
d[v] = d[u] + Adj[u][j].dis;
}
}
}
}
int main() {
scanf("%d %d %d %d", &s, &t, &A, &B);
for(int i = ; i < s; i++) {
//首先讀入第i個城市機場資訊并存儲在airp中
airport tmpA;
for(int j = ; j < ; j++) {
node tmpN;
scanf("%d %d", &tmpN.x, &tmpN.y);
tmpA.s.push_back(tmpN); //将三個結點存入
}
tmpA.s.push_back(findLastPoint(tmpA.s[], tmpA.s[], tmpA.s[])); //存入第四個結點
scanf("%d", &tmpA.T);
airp.push_back(tmpA);
//下面是存儲鄰接表
//本城市内部
for(int j = ; j < ; j++) { //該城市四個機場每兩個機場之間距離和開銷
for(int k = ; k < ; k++){
if(j != k) {
NODE tmp;
tmp.v = i* + k;
tmp.dis = D(tmpA.s[j], tmpA.s[k]) * tmpA.T;
Adj[i* + j].push_back(tmp);
}
}
}
//不同城市間
for(int j = ; j < ; j++) { //對本城市四個機場 j
for(int k = ; k < i; k++) { //對前面每個城市k
for(int l = ; l < ; l++) { //對目标城市的四個機場l
NODE tmp;
tmp.v = k* + l;
tmp.dis = D(tmpA.s[j], airp[k].s[l]) * t;;
Adj[i* + j].push_back(tmp);
tmp.v = i* + j;//雙向鄰接表
Adj[k* + l].push_back(tmp);
}
}
}
}
//計算以出發城市的四個機場為起點和以目标城市的四個機場為終點的16個最短距離,取其最小值
double dis[];
for(int i = ; i < ; i++) {
Dijkstra((A - )* + i);
dis[i] = MIN(d[(B - )*], d[(B - )* + ], d[(B - )* + ], d[(B - )* + ] );
}
printf("%.1f\n", MIN(dis[], dis[], dis[], dis[]));
return ;
}