zoukankan      html  css  js  c++  java
  • ZOJ3794 Greedy Driver [BFS]

    题目地址: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3794

    题目描述:

    N个城市,M条有向边。要从城市1开车到城市N,中途可以加油,也可以倒卖一次油,问最多能赚多少钱。

    油箱容量是C。N个城市中有P个城市(p1, p2…)可以任意免费加油; 有Q个城市(q1,q2…),可以卖油(价格为pri1,pri2…),但全程只能在一座城市卖一次油;每条边都会消耗一定的油。在一开始,油箱是满的。如果能从城市1到达城市N,输出最多可以赚的钱,否则输出-1。

    解题思路:

        一开始读错题还在考虑遍历城市的问题,后来发现不用遍历每座城市。。于是问题就很简单了。因为只能卖一次油,状态也很好保存。

        每个节点(城市)维护一下几个值:

            isReachable - 是否能从城市1走到

            isPassable – 在装满油箱时,能否从这个城市走到城市N

            leastUnit – 从这个城市走到城市N,一开始至少要装多少油

            pendingMaxUnit – 走过这座城市时,在还没有卖过油的状态下,油箱最多能剩多少油

            soldMaxEarn – 走过这座城市时,已经曾经卖过一次油,并且当前的剩余油量不低于leastUnit的条件下,赚到最多的钱

            isFuelStation – 是否可以加油

            canSellFuel – 是否可以卖油

            price – 如果可以卖油,每单位的油价

        首先从城市N反向跑一个BFS,标记isPassable并计算出leastUnit。

        再从城市1跑一个BFS,计算出isReachable,pendingMaxUnit,soldMaxEarn。

    源代码:

      1 //zoj3794_zzy_2014.07.15_AC_graph BFS_DP
      2 #include <iostream>
      3 #include <queue>
      4 
      5 using namespace std;
      6 
      7 class Edge
      8 {
      9 public:
     10     Edge(int v, int c, Edge *p): vid(v), cost(c), next(p) {}
     11     int vid, cost;
     12     Edge *next;
     13 };
     14 
     15 class Vertex
     16 {
     17 public:
     18     Vertex() {}
     19     bool isReachable; //can through the beginning to this vertex with capacity C.
     20     bool isPassable; //can through this vertex to the end with the capacity C.
     21     int leastUnit; //from this vertex to the end, need at least leastUnit unit fuel. leastUnit can be larger than maximum capacity C.
     22     int pendingMaxUnit; //when pass this vertex and never sold fuel, the maximum left unit of fuel. This can be less than leastUnit.
     23     int soldMaxEarn; //when pass this vertex and sold fuel and left fuel no less than leastUnit, the maximum money earned.
     24     bool isFuelStation;
     25     bool canSellFuel;
     26     int price;
     27     Edge *ep;
     28     Edge *bep;
     29 };
     30 
     31 class GreedyDriver
     32 {
     33 public:
     34     GreedyDriver(int n, int m, int c): N(n), M(m), C(c) {
     35         for(int idx = 1; idx <= N; ++idx) {
     36             graph[idx].isReachable = false;
     37             graph[idx].isPassable = false;
     38             graph[idx].leastUnit = -1;
     39             graph[idx].pendingMaxUnit = -1;
     40             graph[idx].soldMaxEarn = -1;
     41             graph[idx].isFuelStation = false;
     42             graph[idx].canSellFuel = false;
     43             graph[idx].price = 0;
     44             graph[idx].ep = NULL;
     45             graph[idx].bep = NULL;
     46         }
     47     }
     48     ~GreedyDriver() {
     49         for(int idx = 1; idx <= N; ++idx) {
     50             Edge *p = graph[idx].ep;
     51             while(p != NULL) {
     52                 Edge *q = p;
     53                 p = p -> next;
     54                 delete q;
     55             }
     56         }
     57     }
     58     void construct();
     59     void solve();
     60     int ans();
     61 private:
     62     int N,M,C;
     63     Vertex graph[1001];
     64     void iniLeastUnit();
     65     void BFS();
     66 };
     67 
     68 void GreedyDriver::construct()
     69 {
     70     for(int idx = 1; idx <= M; ++idx) {
     71         int s, t, l;
     72         cin >> s >> t >> l;
     73         Edge *p = new Edge(t, l, graph[s].ep);
     74         graph[s].ep = p;
     75         Edge *q = new Edge(s, l, graph[t].bep);
     76         graph[t].bep = q;
     77     }
     78     int P;
     79     cin >> P;
     80     while(P--) {
     81         int vid;
     82         cin >> vid;
     83         graph[vid].isFuelStation = true;
     84     }
     85     int Q;
     86     cin >> Q;
     87     while(Q--) {
     88         int vid, pri;
     89         cin >> vid >> pri;
     90         graph[vid].canSellFuel = true;
     91         graph[vid].price = pri;
     92     }
     93 }
     94 
     95 int GreedyDriver::ans()
     96 {
     97     if(graph[N].isReachable == false)
     98         return -1;
     99     int maxEarn = 0;
    100     for(int idx = 1; idx <= N; ++idx) {
    101         if(graph[idx].isReachable && graph[idx].isPassable && graph[idx].soldMaxEarn > maxEarn)
    102             maxEarn = graph[idx].soldMaxEarn;
    103     }
    104     return maxEarn;
    105 }
    106 
    107 void GreedyDriver::iniLeastUnit()
    108 {
    109     bool inQueue[1001];
    110     for(int idx = 1; idx <= N; ++idx)
    111         inQueue[idx] = false;
    112     graph[N].leastUnit = 0;
    113     queue<int> Q;
    114     while(!Q.empty()) Q.pop();
    115     Q.push(N);
    116     inQueue[N] = true;
    117     while(!Q.empty()) {
    118         int fid = Q.front();
    119         Q.pop();
    120         inQueue[fid] = false;
    121         int fLeastUnit = graph[fid].isFuelStation ? 0 : graph[fid].leastUnit;
    122         Edge *p = graph[fid].bep;
    123         while(p != NULL) {
    124             int sid = p -> vid;
    125             int sLeastUnit = fLeastUnit + p -> cost;
    126             if(graph[sid].leastUnit == -1 || graph[sid].leastUnit > sLeastUnit) {
    127                 graph[sid].leastUnit = sLeastUnit;
    128                 if(graph[sid].leastUnit <= C)
    129                     graph[sid].isPassable = true;
    130                 if(graph[sid].isPassable && inQueue[sid] == false) {
    131                     Q.push(sid);
    132                     inQueue[sid] = true;
    133                 }
    134             }
    135             p = p-> next;
    136         }
    137     }
    138 }
    139 
    140 void GreedyDriver::BFS()
    141 {
    142     bool inQueue[1001];
    143     for(int idx = 1; idx <= N; ++idx)
    144         inQueue[idx] = false;
    145     if(graph[1].isPassable == false)
    146         return;
    147     graph[1].isReachable = true;
    148     graph[1].pendingMaxUnit = C;
    149     if(graph[1].canSellFuel) {
    150         if(graph[1].isFuelStation)
    151             graph[1].soldMaxEarn = C * graph[1].price;
    152         else if(graph[1].pendingMaxUnit > graph[1].leastUnit)
    153             graph[1].soldMaxEarn = (graph[1].pendingMaxUnit - graph[1].leastUnit) * graph[1].price;
    154     }
    155     queue<int> Q;
    156     while(!Q.empty()) Q.pop();
    157     Q.push(1);
    158     inQueue[1] = true;
    159     while(!Q.empty()) {
    160         int fid = Q.front();
    161         Q.pop();
    162         inQueue[fid] = false;
    163         Edge *p = graph[fid].ep;
    164         while(p != NULL) {
    165             int sid = p -> vid;
    166             if(graph[sid].isPassable) {
    167                 if(graph[fid].pendingMaxUnit - (p -> cost) >= (graph[sid].isFuelStation ? 0 : graph[sid].leastUnit)) {
    168                     if(graph[sid].isReachable == false) {
    169                         Q.push(sid);
    170                         inQueue[sid] = true;
    171                     }
    172                     graph[sid].isReachable = true;
    173                     if(graph[sid].isFuelStation)
    174                         graph[sid].pendingMaxUnit = C;
    175                     else {
    176                         if(graph[fid].pendingMaxUnit - (p -> cost) > graph[sid].pendingMaxUnit) {
    177                             graph[sid].pendingMaxUnit = graph[fid].pendingMaxUnit - (p -> cost);
    178                             if(inQueue[sid] == false)
    179                                 Q.push(sid);
    180                             inQueue[sid] = true;
    181                         }
    182                     }
    183                     if(graph[sid].canSellFuel) {
    184                         if(graph[sid].isFuelStation)
    185                             graph[sid].soldMaxEarn = C * graph[sid].price;
    186                         else if(graph[sid].pendingMaxUnit > graph[sid].leastUnit &&
    187                                 (graph[sid].pendingMaxUnit - graph[sid].leastUnit) * graph[sid].price > graph[sid].soldMaxEarn)
    188                             graph[sid].soldMaxEarn = (graph[sid].pendingMaxUnit - graph[sid].leastUnit) * graph[sid].price;
    189                     }
    190                 }
    191             }
    192             p = p-> next;
    193         }
    194     }
    195 }
    196 
    197 void GreedyDriver::solve()
    198 {
    199     graph[1].isReachable = true;
    200     graph[N].isPassable = true;
    201     iniLeastUnit();
    202     BFS();
    203 }
    204 
    205 int main()
    206 {
    207     int n,m,c;
    208     while(cin >> n >> m >> c) {
    209         GreedyDriver *gd = new GreedyDriver(n, m, c);
    210         gd -> construct();
    211         gd -> solve();
    212         cout << gd -> ans() << endl;
    213         delete gd;
    214     }
    215     return 0;
    216 }
  • 相关阅读:
    PHP代码审计-command injection-dvwa靶场
    PHP代码审计-Brute Force-dvwa靶场
    PHP代码审计-XSS
    Linux下安装SQLServer2019
    Linux--每日一个跑路小命令之 chmod 000 -R /
    linux的小命令-fuck
    uni-app 页面样式与布局
    uni-app内置基础组件
    uni-app pages.json常用配置
    uni-app项目目录和文件作用
  • 原文地址:https://www.cnblogs.com/Lattexiaoyu/p/3847407.html
Copyright © 2011-2022 走看看