[四連測(二)]路徑規劃(path)
阿新 • • 發佈:2018-12-31
題目描述
有n個點,m條無向邊,有A,B兩個人,初始時刻A在點1,B在點2,他們要走到點n去。A每走一條邊,要消耗B單位能量,B每走一條邊,要消耗E單位能量。如果A,B相伴走,則只消耗P單位的能量。請問A,B走到點n,最少要消耗多少能量?
輸入資料保證1和n,2和n連通。
輸入
第一行包含整數B,E,P,N和M,所有的整數都不超過40000,N>=3.
接下來M行,每行兩個整數,表示該無向邊連線的兩個頂點。
輸出
一個整數,表示最小要消耗的能量。
樣例輸入
4 4 5 8 8 1 4 2 3 3 4 4 7 2 5 5 6 6 8 7 8
樣例輸出
22
解題思路
看起來還挺複雜的,令人想打暴搜,不過,此題倒真是跟搜尋有關,需要利用圖的遍歷。我們要求的路程其實就可以看成是兩人走到一個點,然後再一起走到n點所用的最小花費,由於每走一步花費固定,我們就可以用3個dis陣列來儲存三個點(1,2,n)到i點的最小步數,這樣處理,我們不用通過什麼SPFA那些的圖論演算法,用深搜就可以解決了。最後再列舉1到n,求出這三個路程的最小值即可。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<vector> #include<queue> #include<map> #include<algorithm> #include<cstdlib> #define N 40005 using namespace std; /*struct edge(){ int u,v; edge(){}; edge(int U,int V){ u = U; v = V; } };*/ int b,e,p,n,m , dis1[N], dis2[N],dis3[N],vis[N] , ans = N*N; int que[N],head,tail; vector<int>G[N]; void bfs(int step,int dis[]){ memset(vis,0,sizeof(vis)); dis[step] = 0; vis[step] = 1; head = tail = 1; que[head] = step; while (head <= tail){ int t = que[head]; int len = G[t].size(); for (int i = 0; i < len ; i ++ ){ if (!vis[G[t][i]]){ que[++ tail] = G[t][i]; vis[G[t][i]] = 1; dis[G[t][i]] = dis[t] + 1; } } head ++ ; } } int main(){ scanf("%d%d%d%d%d",&b,&e,&p,&n,&m); for (int i = 1;i <= m ;i ++ ){ int a,b; scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } bfs(1,dis1); bfs(2,dis2); bfs(n,dis3); for (int i = 1 ;i <= n;i ++ ){ ans = min(ans , dis1[i] * b + dis2[i] * e + dis3[i] * p); } printf("%d",ans); }
總結
這樣看起來這道題挺水啊,事實上是這樣的,基本沒考到什麼高階演算法,關鍵看你是否找到了題目中這樣的性質或者說是這樣做的思路。事實證明一些圖論題目可以說並沒有這麼難吧。考試的時候可以說是沒怎麼看這道題,看了一下,發現是有關圖論的,當場就有點怕,又一直在想這是怎樣的演算法才可以通過,都沒有仔細算過。當時還想了一些特殊的點,但對於正確演算法都沒有太大的實際意義。於是,我發現題目當中的一些特殊性質還是要能夠抓住,這樣才能令做題如有神助。(實話說,第一道題耗費了我大量時間,導致全盤爆炸,可以說是模擬考試中考得最差的一次,不過事實證明,這道題如果我打了樣例,我將上升近10名。。。。)