容易证明,使用优先队列的BFS中,每个状态(或者说阶段)第一次出队时即为该状态的最小代价。
具体在这道题中,当终点T的某个状态第一次被取出时,即为最优答案/
(我不会说我第一次写没有用记忆化然后TLE了)
1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 #include <vector> 5 #include <cstring> 6 #include <iostream> 7 using namespace std; 8 const int MAXN = 1000 + 20; 9 const int INF = 0x3f3f3f3f; 10 11 int N, M, Q; 12 int C, S, T; 13 int cc[MAXN], d[MAXN][110]; 14 15 struct edge 16 { 17 int to, dis; 18 edge(int v = 0, int c = 0) : to(v), dis(c) {} 19 }; 20 21 vector<edge> g[MAXN]; 22 23 struct P 24 { 25 int city, fuel, cost; 26 bool operator >(const P &x) const{ 27 return cost > x.cost; 28 } 29 }ans; 30 31 inline bool solve() 32 { 33 priority_queue<P, vector<P>, greater<P> > q; 34 35 d[S][0] = 0; 36 P s; 37 s.city = S, s.fuel = 0, s.cost = 0; 38 q.push(s); 39 while(!q.empty()) 40 { 41 P p = q.top(); q.pop(); 42 if(p.city == T) 43 { 44 ans = p; return true; 45 } 46 if(p.fuel < C && d[p.city][p.fuel + 1] > d[p.city][p.fuel] + cc[p.city]) 47 { 48 d[p.city][p.fuel + 1] = d[p.city][p.fuel] + cc[p.city]; 49 P nxt = p; 50 nxt.fuel++; 51 nxt.cost += cc[p.city]; 52 q.push(nxt); 53 } 54 55 int u = p.city; 56 for(int i = 0; i < (int) g[u].size(); i++) 57 { 58 const edge &e = g[u][i]; 59 if(e.dis <= p.fuel && d[e.to][p.fuel - e.dis] > p.cost) 60 { 61 d[e.to][p.fuel - e.dis] = p.cost; 62 P nxt = p; 63 nxt.fuel -= e.dis; 64 nxt.city = e.to; 65 q.push(nxt); 66 } 67 } 68 } 69 return false; 70 } 71 72 int main() 73 { 74 //freopen("11367.txt", "r", stdin); 75 cin>>N>>M; 76 for(int i = 0; i < N; i++) 77 scanf("%d", &cc[i]); 78 79 int u, v, c; 80 for(int i = 1; i <= M; i++) 81 { 82 scanf("%d%d%d", &u, &v, &c); 83 g[u].push_back(edge(v, c)); 84 g[v].push_back(edge(u, c)); 85 } 86 87 cin>>Q; 88 while(Q--) 89 { 90 cin>>C>>S>>T; 91 memset(d, 0x3f, sizeof(d)); 92 if(solve()) cout<<ans.cost<<endl; 93 else puts("impossible"); 94 } 95 return 0; 96 }