【最短路】Pod
版權聲明:本篇隨筆版權歸作者Etta(http://www.cnblogs.com/Etta/)所有,轉載請保留原地址!
現在讓我們來對一個交通運輸圖進行研究,這可能是一個公交車的線路網、有軌電車線路網、地下鐵的線路網或是其他的一個什么。這個圖中的頂點(從1到n標號)為車站,邊(pi ,pj)(這里pi 1 pj)表示在頂點pi和頂點pj間存在一條直接連接兩點的路(1 £ pi, pj £ n)。
在圖中有從1到k編號的k條運輸路線,第l號路線是用一個車站序列pl,1, pl,2, …, pl,sl來描述的,它們為使用這個線路的車輛將依次經過的車站。并且我們給出它們之間的距離rl,1, rl,2, …, rl,sl-1,其中rl,i表示從車站pl,i到車站pl,i+1所需的時間。對于一條線路來說,它上面所有的車站都是不相同的(也就是說,若i 1 j,則pl,i 1 pl,j)。且線路l將以頻率cl運行。這里cl為集合{6, 10, 12, 15, 20, 30 ,60}中的一個數,它表示每個小時的0, cl, 2cl, …, 60分鐘的時候在路線l上的將有兩輛車同時從車站pl,1和pl,sl出發相對著行進。
在這樣一個運輸網絡中,我們想從其中的一個車站x出發用盡可能少的時間到達車站y。這里我們假設最少的時間不會超過24個小時,且在中途換車的時候的時間不計。
示例:
在下圖中你可以看到一個具有六個車站和兩條路線的運輸網絡。路線一上的車站序列為1、3、4、6,路線二上的車站序列為2、4、3、5,且兩條路線的頻率分別為c1=15和c2=20。車輛在各車站間移動時的耗費都分別用1和2的下標標在了圖上。
?
現在我們假設在23點30分的時候我們在車站5想要到車站6去。我們必須等上10分鐘才可以搭上一輛路線2的車離開。然后我們就面臨著兩種選擇:一種是在23點51分到車站3等上3分鐘并改乘路線1的車于0點16分到達車站6;另一種是在0點8分到達車站4等上13分鐘再換路線1的車于0點31分到達車站6。顯然最早我們能在0點16分到達車站6。
任務:
請寫一個程序:
從文本文件POD.IN中讀入對該交通運輸網的描述、起點和終點、還有出發的時間;
找出從起點到終點的最少時間;
把最找到達終點的時間輸出到文本文件POD.OUT中。
輸入格式:
在文本文件POD.IN的第一行包括六個用空格分開的整數,分別為:
n,1 £ n £ 1000,為車站的數目;
k,1 £ k £ 2000,為路線的數目;
x,1 £ x £ n,為起點的車站編號;
y,1 £ y £ n,為終點的車站編號;
gx,0 £ gx £ 23,為出發時間的小時數;
mx,0 £ mx £ 59,為出發時間的分鐘數。
車站是從1到n編號的,運輸路線是用1到k編號的。以下的3k行為對運輸路線的描述。這些行中每3行構成一個對一條路線的描述,第k個三行的意義如下:
第一行包括兩個用空格分開的整數,sl(2 £ sl£ n)為該路線上車站的數目,還有cl({6, 10, 12, 15, 20, 30, 60}中的一個元素),為該路線運行的頻率;
第二行包括sl個用空格分開的不同的整數,為pl,1, pl,2, …,pl,sl(1£ pl,i£ n),即該路線上的車站;
第三行包括sl-1個整數rl,1, rl,2, …,rl,sl-1為在路線上相鄰兩個車站間移動所需的時間(1£ rl,i£ 240)。
在所有的運輸路線上的總車站數不超過4000(也就是說s1 + s2 + … + sk £ 4000)。
輸出格式:
你的程序應該在文本文件POD.OUT中輸出兩個整數gy(0£ gy£ 23)和my(0£ my£ 59),表示到達y點時的小時數和分鐘數。
樣例:
輸入(POD.IN):
6 2 5 6 23 30
4 15
1 3 4 6
9 12 10
4 20
5 3 4 2
11 17 11
輸出(POD.OUT):
0 16
?
一、分析問題
?????? 這是一個加限制條件的最短路問題。
?
二、解決問題
?????? Spfa+等待時間的計算(詳見代碼)
?
三、代碼實現
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int A = 4010*2,B = 1010,inf = 4e8; 8 int n,m,k,st,en,gx,mx,sum; 9 struct edge{ 10 int to,nxt,len,c,d; 11 }e[A]; 12 int head[B],dis[B],ex[B]; 13 queue<int>q; 14 15 void build(int f,int t,int l,int k,int c) 16 { 17 ++sum; 18 e[sum].nxt=head[f]; 19 head[f]=sum; 20 e[sum].to=t; 21 e[sum].len=l; 22 e[sum].d=k; 23 e[sum].c=c; 24 } 25 26 void init() 27 { 28 int s2,c2,sum=0,sum1=0,d[B],s[B]; 29 scanf("%d%d%d%d%d%d",&n,&k,&st,&en,&gx,&mx); 30 for(int i=1;i<=k;++i) 31 { 32 sum=0; 33 sum1=0; 34 scanf("%d%d",&s2,&c2); 35 for(int j=1;j<=s2;++j)scanf("%d",&s[j]); 36 for(int j=1;j<s2;++j)scanf("%d",&d[j]),sum+=d[j]; 37 for(int j=2;j<=s2;++j) 38 { 39 build(s[j-1],s[j],d[j-1],sum1,c2); 40 sum-=d[j-1]; 41 sum1+=d[j-1]; 42 build(s[j],s[j-1],d[j-1],sum,c2); 43 } 44 } 45 } 46 47 48 void calc(int x,int y)//計算等待時間w 49 { 50 int w=e[y].d;//此時w是車輛到達的時刻(時間點) 51 if(dis[x]<w)//車輛仍未到達,找在這之后的車 52 { 53 while(w-e[y].c>=dis[x]) 54 w-=e[y].c; 55 w-=dis[x]; 56 } 57 else//車輛已走,找在這之前的車 58 { 59 w=dis[x]; 60 while(w>e[y].d) 61 w-=e[y].c; 62 w=e[y].d-w; 63 } 64 if(dis[e[y].to]>dis[x]+e[y].len+w) 65 { 66 dis[e[y].to]=dis[x]+e[y].len+w; 67 if(!ex[e[y].to]) 68 { 69 ex[e[y].to]=1; 70 q.push(e[y].to); 71 } 72 } 73 } 74 75 void SPFA() 76 { 77 for(int i=1;i<=n;++i)dis[i]=inf; 78 dis[st]=mx; 79 q.push(st); 80 while(!q.empty()) 81 { 82 int t=q.front(); 83 ex[t]=0; 84 q.pop(); 85 for(int i=head[t];i;i=e[i].nxt) 86 calc(t,i); 87 } 88 } 89 90 void print() 91 { 92 int h,m; 93 h=gx; 94 m=dis[en]; 95 if(m>59) 96 { 97 h+=(m/60); 98 m%=60; 99 } 100 h%=24; 101 printf("%d %d\n",h,m); 102 } 103 104 int main() 105 { 106 init(); 107 SPFA(); 108 print(); 109 return 0; 110 }?
轉載于:https://www.cnblogs.com/Etta/p/6363418.html
總結
- 上一篇: 洛谷P1396营救(最小生成树)
- 下一篇: 代码规范,代码风格