1. 程式人生 > >car的旅行路線

car的旅行路線

AI lse 圖例 一起 family copy scanf ble 簡便

https://www.luogu.org/problemnew/show/P1027

題目描述

又到暑假了,住在城市A的Car想和朋友一起去城市B旅遊。她知道每個城市都有四個飛機場,分別位於一個矩形的四個頂點上,同一個城市中兩個機場之間有一條筆直的高速鐵路,第I個城市中高速鐵路了的單位裏程價格為Ti,任意兩個不同城市的機場之間均有航線,所有航線單位裏程的價格均為t。

技術分享圖片

圖例(從上而下)

機場 高速鐵路

飛機航線

  註意:圖中並沒有

標出所有的鐵路與航線。

那麽Car應如何安排到城市B的路線才能盡可能的節省花費呢?她發現這並不是一個簡單的問題,於是她來向你請教。

找出一條從城市A到B的旅遊路線,出發和到達城市中的機場可以任意選取,要求總的花費最少。

輸入輸出格式

輸入格式:

第一行為一個正整數n(0<=n<=10),表示有n組測試數據。

每組的第一行有四個正整數s,t,A,B。

S(0<S<=100)表示城市的個數,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個城市高速鐵路單位裏程的價格。

輸出格式:

共有n行,每行一個數據對應測試數據。 保留一位小數

輸入輸出樣例

輸入樣例#1:
1
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
輸出樣例#1: 47.5


題目解析:
這是一道比較裸的最短路問題,首先是建圖問題,題目只給了一個城市三個點的坐標,設已知三點坐標為(x1,y1) (x2,y2) (x3,y3),如何求(x4,y4)?
因為這是一個垂直,我們可以想到勾股,向量等方法,但不簡便。由於這是個矩形,不難想到對角線中點相等,那麽已知的三個點哪兩個是對角的點呢?
我們可以通過勾股定理求出三條邊,根據邊越大,角越大的規則可以求出直角,設為(x3,y3),不難得出:
x4=x2+x3-x1;
y4=y2+y3-y1;
這樣整個圖的所有點求出,開始建圖。而由於這是個稠密圖,我們建議用鄰接矩陣(手殘用了鄰接表)。
從主觀上看,我們可以以a城市的四個機場為起點,這樣需要跑四次spfa。但是我們可以利用虛點的思想,問題可以轉化為從虛點出發到B城市的spfa。
(假設有一個點:0,它到四個起點的dist==0)
而程序中並不需要把虛點建出來連邊,只需把四個起點的dist設為0即可;
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #define maxn 10001
  7 using namespace std;
  8 int n,s,a,b,u[maxn],v[maxn],fr[maxn],cure,curn,frst[maxn],nst[maxn],que[maxn],head,tail,vis[maxn],T,t[maxn],des,xx[maxn],yy[maxn];
  9 //int ans=0x7ffffff;
 10 float w[maxn],dist[maxn];
 11 int min(int x,int y)
 12 {
 13     return x>y?y:x;
 14 }
 15 void add(int x,int y,float z)
 16 {
 17     u[cure++]=x;v[cure]=y,w[cure]=z;
 18     nst[cure]=frst[x];frst[x]=cure;
 19 }
 20 float dis(int x1,int y1,int x2,int y2)
 21 {
 22     float ans=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
 23     return ans;
 24 }
 25 int main()
 26 {
 27     scanf("%d",&n);
 28     for(int timm=1;timm<=n;timm++)
 29     {
 30         memset(frst,-1,sizeof(frst));
 31         memset(nst,-1,sizeof(nst));
 32         memset(u,0,sizeof(u));
 33         memset(v,0,sizeof(v));
 34         memset(t,0,sizeof(t));
 35         memset(w,0,sizeof(w));
 36         memset(que,0,sizeof(que));
 37         memset(vis,0,sizeof(vis));
 38         memset(fr,0,sizeof(fr));
 39         memset(xx,0,sizeof(xx));
 40         memset(yy,0,sizeof(yy));
 41         curn=0;cure=0;
 42         head=tail=0;
 43         scanf("%d%d%d%d",&s,&T,&a,&b);
 44         for(int i=1;i<=s;i++)
 45         {
 46             int x1,y1,x2,y2,x3,y3,x4,y4,nodex,nodey;
 47             float e1,e2,e3;
 48             scanf("%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&t[i]);
 49             e1=dis(x2,y2,x3,y3);
 50             e2=dis(x1,y1,x3,y3);
 51             e3=dis(x1,y1,x2,y2);
 52             if(e1>e2&&e1>e3)
 53             {
 54                 x4=x2+x3-x1;y4=y2+y3-y1; 
 55             }    
 56             else if(e2>e1&&e2>e3)
 57             {
 58                 x4=x1+x3-x2;y4=y1+y3-y2;
 59             }    
 60             else if(e3>e1&&e3>e2)
 61             {
 62                 x4=x1+x2-x3;y4=y1+y2-y3;
 63             }    
 64             xx[++curn]=x1;yy[curn]=y1;fr[curn]=i;
 65             xx[++curn]=x2;yy[curn]=y2;fr[curn]=i;
 66             xx[++curn]=x3;yy[curn]=y3;fr[curn]=i;
 67             xx[++curn]=x4;yy[curn]=y4;fr[curn]=i;
 68         }
 69         for(int j=1;j<=curn;j++)
 70             for(int k=1;k<=curn;k++)
 71             {
 72                 if(j==k)
 73                     continue;
 74                 if(fr[j]==fr[k])
 75                 {
 76                     if(fr[j]==a||fr[j]==b)
 77                     {
 78                         add(j,k,0);
 79                         if(fr[j]==b)
 80                             des=j;
 81                     }
 82                     else
 83                     {
 84                         float fee=dis(xx[j],yy[j],xx[k],yy[k])*t[fr[j]];
 85                         add(j,k,fee);
 86                     }
 87                 }
 88                 else
 89                 {
 90                     float fee=dis(xx[j],yy[j],xx[k],yy[k])*T;
 91                     add(j,k,fee);
 92                 }
 93             }
 94         for(int j=1;j<=curn;j++)
 95         {
 96             dist[j]=0x7fffffff;
 97             if(fr[j]==a)
 98             {
 99                 dist[j]=0;
100                 que[tail]=j;
101             }    
102         }
103         tail++;
104         while(head<tail)
105         {
106             int node=que[head];
107             head++;
108             if(fr[node]!=a) vis[node]=0;
109             for(int ed=frst[node];ed!=-1;ed=nst[ed])
110             {
111                 int to=v[ed];
112                 if(dist[to]>dist[node]+w[ed])
113                 {
114                     dist[to]=dist[node]+w[ed];
115                     if(!vis[to])
116                     {
117                         vis[to]=1;
118                         que[tail++]=to;
119                     }
120                 }
121                 if(fr[to]==a&&!vis[to])
122                 {
123                     vis[to]=1;
124                     que[tail++]=to;
125                 }
126             }
127         }
128         printf("%0.1f\n",dist[des]);        
129     }
130     return 0;
131 }

 


car的旅行路線