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 }

ZOJ3794 Greedy Driver [BFS]

时间: 2024-10-14 00:44:12

ZOJ3794 Greedy Driver [BFS]的相关文章

ZOJ 3794 Greedy Driver spfa

题意: 给定n个点,m条有向边,邮箱容量. 起点在1,终点在n,开始邮箱满油. 下面m行表示起点终点和这条边的耗油量(就是长度) 再下面给出一个数字m表示有P个加油站,可以免费加满油. 下面一行P个数字表示加油站的点标. 再下面一个整数Q 下面Q行 u v 表示在u点有销售站,可以卖掉邮箱里的任意数量的油,每以单位v元. 问跑到终点能获得最多多少元. 先求个每个点的最大剩余油量 f[i], 再把边反向,求每个点距离终点的最短路 dis[i]. 然后枚举一下每个销售点即可,( f[i] - dis

ZOJ 3794 Greedy Driver

Greedy Driver Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on ZJU. Original ID: 3794 64-bit integer IO format: %lld      Java class name: Main Edward is a truck driver of a big company. His daily work is driving a truck from o

ZOJ - 3794 Greedy Driver 最短路

首先正向跑一遍1为起点的最短路,注意松弛过程如果走到加油站则dis=0,并且路上任意时刻dis都不能大于C,判断dis[n]是否<=C就能判断无解情况了. 然后反向建图再跑一次N为起点的最短路,这样可以求到每个点到n点的最短路. 对于每一个可以交易的城市,C-dis1[i]-dis2[i]就是多出来可以卖掉的油. #include<iostream> #include<cstdlib> #include<cstring> #include<cmath>

ZOJ Monthly, June 2014 月赛BCDEFGH题题解

比赛链接:点击打开链接 上来先搞了f.c,,然后发现状态不正确,一下午都是脑洞大开,, 无脑wa,无脑ce...一样的错犯2次.. 硬着头皮搞了几发,最后20分钟码了一下G,不知道为什么把1直接当成不能加油的站就会wa..太弱.. 唔···太懒第二天才发题解.. B:Gears 并查集 题解:点击打开链接 C:Consecutive Blocks 离散化一下然后模拟 题解:点击打开链接 D:An Easy Game 设dp[i][j]为前i个位置已经匹配了j个位置的方法数. #include <

ZOJ Monthly, June 2014 解题报告

A.Another Recurrence Sequence B.Gears 题目大意:有n个齿轮,一开始各自为一组,之后进行m次操作,包括以下4种类型: 1.合并两组齿轮,合并的两个应该反向旋转 2.把某个齿轮从所在组删除,自为一组,但不影响同组其它齿轮的状态与关系 3.询问两个齿轮是同向.反向或无关系(即不在同一组) 4.询问某个齿轮所在组的齿轮总数 分析:典型的并查集操作,但是注意两点: 1.由于操作3要询问两个齿轮的相对状态,因此对并查集中每个元素应当保存它的状态信息.状态是相对的,只需要

2014牡丹江网络预选赛F题(隐式图BFS暴搜)zoj3814

Sawtooth Puzzle Time Limit: 10 Seconds      Memory Limit: 65536 KB Recently, you found an interesting game called Sawtooth Puzzle. This is a single-player game played on a grid with 3 x 3 cells. Each cell contains a part of an image. Besides, each ed

BNU 49102进化之地(Evoland) BFS

进化之地(Evoland) Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Font Size:  +   - Type:   None Graph Theory      2-SAT     Articulation/Bridge/Biconnected Com

Ural 1096-Get the Right Route Plate!(bfs)

1096. Get the Right Route Plate! Time limit: 1.0 second Memory limit: 64 MB Everybody who had ridden a Ekaterinburg bus could notice that on the inner side of the plate with the number of the route there was a number of another route. One day the dri

POJ--2435(bfs)

Navigating the City Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description A dip in the milk market has forced the cows to move to the city. The only employment available is in the venerable field of tax