1. 程式人生 > >Car的旅行路線(NOIP2001)

Car的旅行路線(NOIP2001)

這裡寫圖片描述

今天,是個重大一天,因為從今天起,為了大家有更好的體驗,我將對我的題解進行全新改版!!
(不滿的lovechq:你不就還有5天就去備戰高考了嗎?現在改版有啥用?
來自cgg的答覆:雖然,在過幾天,我會和大家依依不捨地道別,因為我真的要去備戰高考了,但是明年暑假我會強勢迴歸的!請各位放心)

知識點

(cgg解釋:這裡是為了讓大家看到此題涉及的知識點,可以提前預習)

計算幾何

向量,兩點間距離公式

圖論

鄰接矩陣、Floyd(最短路)

基本思路

(cgg解釋:這個版塊是為了有些巨神準備的,因為巨神有時候只是一時短路,只要簡單看看思路就可以了,所以在這裡把思路簡單整理一下,便於檢視)

用資料結構去儲存城市和點。
用向量求第四個點。
然後建圖,算出每兩個點之間的花費。
Floyd

詳細解釋

(cgg解釋:這個版塊是解釋上面沒有說清楚的地方)

儲存城市和點

我們可以寫兩個結構體,一個是點,一個是城市。

計算第四個點

我們先來看看怎麼計算第四個點。
我們可以先計算出來已知的三個點兩兩之間的距離,由於是矩形,我們一定有一個斜邊,也就是矩形的對角線,也就是我們求出的三個距離中最長的那一個
那麼接下來怎麼處理呢?
我們來看一個圖:
這裡寫圖片描述

其中ABC三點已知。
我們觀察向量BC和向量AD(你不知道向量?快戳開

因為四邊形ABCD是矩形,所以向量BC和向量AD應該相等。
所以(x3-x2,y3-y2)=(x4-x1,y4-y1)
所以我們就可以求出來第四個點了:
x4=x3+x1-x2
y4=y3+y1-y2
這樣就大功告成了!

建圖計算距離

然後注意列舉順序,依次計算出每一個點到同一個城市其他點的花費,再計算到其他城市每一個點的花費。
注意不只是距離,還要乘上每單位長度的花費。
用鄰接矩陣就好了

Floyd

最簡單的最短路演算法,就不說了。
最後只要對起始和終點城市的每個飛機場之間的距離進行列舉,得到最小值即可。

難度點評

(cgg解釋:客觀地評價)

不是很難,沒有什麼思維難度,重在考察程式碼能力。

程式碼

(cgg解釋:這顯然是題解不可少的一部分)

!!!請注意:vijos的題目和洛谷的不一樣
本處只提供洛谷的程式碼
vijos的題目沒有多組資料,且保留兩位小數

#include<cstdio>
#include<cstring> #include<algorithm> #include<cmath> using namespace std; struct point{ int num; int x,y; }; struct city{ point poi[5]; int w; }; int T; int n,t,A,B; city c[105]; int ind; double mapp[405][405]; double dis(point poi1,point poi2){ return sqrt((poi1.x-poi2.x)*(poi1.x-poi2.x)+(poi1.y-poi2.y)*(poi1.y-poi2.y)); } void getpoi4(city& ci){ double l12=dis(ci.poi[1],ci.poi[2]),l13=dis(ci.poi[1],ci.poi[3]),l23=dis(ci.poi[2],ci.poi[3]); if(l12>l13&&l12>l23){ ci.poi[4].x=ci.poi[1].x+ci.poi[2].x-ci.poi[3].x; ci.poi[4].y=ci.poi[1].y+ci.poi[2].y-ci.poi[3].y; }else if(l13>l12&&l13>l23){ ci.poi[4].x=ci.poi[1].x+ci.poi[3].x-ci.poi[2].x; ci.poi[4].y=ci.poi[1].y+ci.poi[3].y-ci.poi[2].y; }else{ ci.poi[4].x=ci.poi[3].x+ci.poi[2].x-ci.poi[1].x; ci.poi[4].y=ci.poi[3].y+ci.poi[2].y-ci.poi[1].y; } } int main(){ scanf("%d",&T); ind=1; while(T--){ memset(mapp,0x42,sizeof(mapp)); scanf("%d%d%d%d",&n,&t,&A,&B); for(int i=1;i<=n;i++){ scanf("%d%d%d%d%d%d%d",&c[i].poi[1].x,&c[i].poi[1].y,&c[i].poi[2].x,&c[i].poi[2].y,&c[i].poi[3].x,&c[i].poi[3].y,&c[i].w); getpoi4(c[i]); c[i].poi[1].num=ind++; c[i].poi[2].num=ind++; c[i].poi[3].num=ind++; c[i].poi[4].num=ind++; } for(int i=1;i<=n;i++){ for(int j=1;j<=4;j++){ point cur=c[i].poi[j]; for(int k=j+1;k<=4;k++){ point kkk=c[i].poi[k]; mapp[cur.num][kkk.num]=mapp[kkk.num][cur.num]=dis(cur,kkk)*(double)c[i].w; } for(int k=i+1;k<=n;k++){ for(int l=1;l<=4;l++){ point kkk=c[k].poi[l]; mapp[cur.num][kkk.num]=mapp[kkk.num][cur.num]=dis(cur,kkk)*(double)t; } } } } for(int k=1;k<ind;k++){ for(int i=1;i<ind;i++){ for(int j=1;j<ind;j++){ if(i==j){ mapp[i][j]=0.0; continue; } mapp[i][j]=min(mapp[i][j],mapp[i][k]+mapp[k][j]); } } } double ans=100000000000.0; for(int i=1;i<=4;i++){ for(int j=1;j<=4;j++){ ans=min(ans,mapp[c[A].poi[i].num][c[B].poi[j].num]); } } printf("%.1lf\n",ans); } return 0; }