zoukankan      html  css  js  c++  java
  • 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
    ",res);
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    js三种存储方式区别
    利用split方法计算字符串中出现字母最多的次数
    图片预加载的三个方法
    页面有大量图片,优化图片的加载方法
    USB通信协议——深入理解
    C/C++回调函数
    显卡工作原理
    include包含头文件的语句中,双引号和尖括号的区别是什么?
    华为2015校园招聘 上机试题
    位操作基础篇之位操作全面总结
  • 原文地址:https://www.cnblogs.com/WABoss/p/5495922.html
Copyright © 2011-2022 走看看