POJ3635 Full Tank?(DP + Dijkstra)

题目大概说,一辆带有一个容量有限的油箱的车子在一张图上行驶,每行驶一单位长度消耗一单位油,图上的每个点都可以加油,不过都有各自的单位费用,问从起点驾驶到终点的最少花费是多少?

这题自然想到图上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\n",res);
79     }
80     return 0;
81 }

 

posted @ 2016-05-15 19:50  WABoss  阅读(441)  评论(0编辑  收藏  举报