题目大概说,一辆带有一个容量有限的油箱的车子在一张图上行驶,每行驶一单位长度消耗一单位油,图上的每个点都可以加油,不过都有各自的单位费用,问从起点驾驶到终点的最少花费是多少?
这题自然想到图上DP,通过最短路来转移方程:
- dp[u][c]表示当前在u点油箱还有c单位油时的最少花费
不过,我T得好惨,因为在转移时我通过枚举在各个结点加多少油转移,这样对于每个状态都for一遍枚举,整个时间复杂度还得乘上转移的代价,即油箱最大容量。。。
事实上,状态dp[u][c]只需要向两个方向转移:
- 向dp[u][c+1]转移,即原地加一单位油
- 向dp[v][c-w(u,v)]((u,v)∈E 且 w(u,v)<=c),即走到下一个结点
另外用SPFA会TLE,用Dijkstra即可,1000×100的状态数稳定AC。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 1111 8 #define MAXM 111111 9 10 struct Edge{ 11 int v,w,next; 12 }edge[MAXM<<1]; 13 int NE,head[MAXN]; 14 void addEdge(int u,int v,int w){ 15 edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u]; 16 head[u]=NE++; 17 } 18 19 int vs,vt,cap; 20 int price[MAXN],d[MAXN][111]; 21 bool vis[MAXN][111]; 22 23 struct Node{ 24 int u,w,d; 25 Node(int _u=0,int _w=0,int _d=0):u(_u),w(_w),d(_d){} 26 bool operator<(const Node &nd)const{ 27 return nd.d<d; 28 } 29 }; 30 31 int dijkstra(){ 32 memset(d,127,sizeof(d)); 33 memset(vis,0,sizeof(vis)); 34 priority_queue<Node> que; 35 for(int i=0; i<=cap; ++i){ 36 d[vs][i]=price[vs]*i; 37 que.push(Node(vs,i,d[vs][i])); 38 } 39 while(!que.empty()){ 40 Node nd=que.top(); que.pop(); 41 if(nd.u==vt) return nd.d; 42 if(vis[nd.u][nd.w]) continue; 43 vis[nd.u][nd.w]=1; 44 if(nd.w<cap && d[nd.u][nd.w+1]>d[nd.u][nd.w]+price[nd.u]){ 45 d[nd.u][nd.w+1]=d[nd.u][nd.w]+price[nd.u]; 46 que.push(Node(nd.u,nd.w+1,d[nd.u][nd.w+1])); 47 } 48 for(int i=head[nd.u]; i!=-1; i=edge[i].next){ 49 int v=edge[i].v; 50 if(edge[i].w>nd.w) continue; 51 int nw=nd.w-edge[i].w; 52 if(d[v][nw]>d[nd.u][nd.w]){ 53 d[v][nw]=d[nd.u][nd.w]; 54 que.push(Node(v,nw,d[v][nw])); 55 } 56 } 57 } 58 return INF; 59 } 60 61 int main(){ 62 int n,m,q,a,b,c; 63 scanf("%d%d",&n,&m); 64 for(int i=0; i<n; ++i){ 65 scanf("%d",price+i); 66 } 67 memset(head,-1,sizeof(head)); 68 while(m--){ 69 scanf("%d%d%d",&a,&b,&c); 70 addEdge(a,b,c); 71 addEdge(b,a,c); 72 } 73 scanf("%d",&q); 74 while(q--){ 75 scanf("%d%d%d",&cap,&vs,&vt); 76 int res=dijkstra(); 77 if(res==INF) puts("impossible"); 78 else printf("%d ",res); 79 } 80 return 0; 81 }