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;
}