1. 程式人生 > >[NOIP提高組2001]Car的旅行路線

[NOIP提高組2001]Car的旅行路線

http://caioj.cn/problem.php?id=1507
問題描述:
又到暑假了,住在城市A的Car想和朋友一起去城市B旅遊。她知道每個城市都有四個飛機場,分別位於一個矩形的四個頂點上,同一個城市中兩個機場之間有一條筆直的高速鐵路,第I個城市中高速鐵路了的單位里程價格為Ti,任意兩個不同城市的機場之間均有航線,所有航線單位里程的價格均為t。
那麼Car應如何安排到城市B的路線才能儘可能的節省花費呢?她發現這並不是一個簡單的問題,於是她來向你請教。找出一條從城市A到B的旅遊路線,出發和到達城市中的機場可以任意選取,要求總的花費最少
這裡寫圖片描述
輸入:
第一行為一個正整數n(0≤n≤10),表示有n組測試資料。
第二行有四個正整數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個城市高速鐵路單位里程的價格。
輸出:
輸出最小費用(結果保留兩位小數)
題解:
首先,輸入只有三個點,所以我們要求第四個點,這裡我們可以用迭代法不停迴圈,直到x1->x2,x2->x3這兩條直線垂直。那麼第四個點的座標就是x1-x2+x3這裡畫個圖就知道了。
然後直接建邊,跑最短路,由於資料範圍不大直接floyd就好了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 10000000  
#define get(x) (x-1)*4+1
using namespace std;
int n;
int s,st,ed,ap;
double T;
struct node{
    double x[4],y[4];
}sa[105];//第i個城市機場的x,y 
double f[4050][4050];//從第i個機場到第j個機場的最短距離 
void getfour(int x)//求第四個點 { double tx[4],ty[4]; memcpy(tx,sa[x].x,sizeof(tx)); memcpy(ty,sa[x].y,sizeof(ty)); while((tx[0]-tx[1])*(tx[2]-tx[1])+(ty[0]-ty[1])*(ty[2]-ty[1]))//畫個圖就知道了,這樣可以判斷直線是否垂直 { int tt=tx[0];tx[0]=tx[1];tx[1]=tx[2];tx[2]=tt; tt=ty[0];ty[0]=ty[1];ty[1]=ty[2
];ty[2]=tt; } sa[x].x[3]=tx[0]-tx[1]+tx[2]; sa[x].y[3]=ty[0]-ty[1]+ty[2]; } double dis(int x1,int y1,int x2,int y2) { return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } int main() { scanf("%d",&n); while(n--) { scanf("%d%lf%d%d",&s,&T,&st,&ed); if(st==ed) {printf("0.00\n");continue;} ap=s*4; for(int i=1;i<=ap;i++) for(int j=1;j<=ap;j++) { f[i][j]=inf; } for(int i=1;i<=s;i++) { for(int j=0;j<3;j++) scanf("%lf%lf",&sa[i].x[j],&sa[i].y[j]); getfour(i);//得到第四個點 //求同一城市,機場間的距離 double yu; scanf("%lf",&yu); for(int u=0;u<4;u++) { for(int v=0;v<4;v++) { if(u==v) continue; f[get(i)+u][get(i)+v]=dis(sa[i].x[u],sa[i].y[u],sa[i].x[v],sa[i].y[v])*yu; } } } //求不同城市的機場間的距離 for(int i=1;i<=s;i++) { for(int j=1;j<=s;j++) { if(i==j) continue; for(int u=0;u<4;u++) { for(int v=0;v<4;v++) { f[get(i)+u][get(j)+v]=dis(sa[i].x[u],sa[i].y[u],sa[j].x[v],sa[j].y[v])*T; // } } } } //floyd求最短路 for(int k=1;k<=ap;k++) for(int i=1;i<=ap;i++) for(int j=1;j<=ap;j++) { f[i][j]=min(f[i][j],f[i][k]+f[k][j]); // } double ans=inf; for(int i=0;i<4;i++) for(int j=0;j<4;j++) { ans=min(ans,f[get(st)+i][get(ed)+j]); //printf("%.2lf\n",f[get(st)+i][get(ed)+j]); } printf("%.2lf\n",ans); } }