BZOJ 1747 [Usaco2005 open]Expedition 探险 贪心

Description

A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Being rather poor drivers, the cows unfortunately managed to run over a rock and puncture the truck's fuel tank. The truck now leaks one unit of fuel every unit of distance it travels. To repair the truck, the cows need to drive to the nearest town (no more than 1,000,000 units distant) down a long, winding road. On this road, between the town and the current location of the truck, there are N (1 <= N <= 10,000) fuel stops where the cows can stop to acquire additional fuel (1..100 units at each stop). The jungle is a dangerous place for humans and is especially dangerous for cows. Therefore, the cows want to make the minimum possible number of stops for fuel on the way to the town. Fortunately, the capacity of the fuel tank on their truck is so large that there is effectively no limit to the amount of fuel it can hold. The truck is currently L units away from the town and has P units of fuel (1 <= P <= 1,000,000). Determine the minimum number of stops needed to reach the town, or if the cows cannot reach the town at all.

    一群奶牛抢了一辆卡车决定前往树林里探险.但是由于它们的驾驶技术太糟,油箱在路上给弄破了,所以它们每前进一个单位的路程就会漏掉一个单位的油,为了修好油箱,奶牛们必须前往最近的城市(不会超过1000000单位路程).在当前位置和城市之间有N(1≤N≤10000)个加油站.奶牛可以在加油站加1到100单位的油.对于人来说,树林是个危险的地方,对奶牛来说,更是这样.所以,奶牛要尽可能的少停站加油.幸运的是,这辆卡车的油箱非常大,你可以认为它的容量是无穷大的.卡车在离城P(1≤P≤1000000)个单位时还有L个单位的油. 你要算出奶牛们至少要停几站才能到城市,或者奶牛们根本到不了城市.

Input

* Line 1: A single integer, N * Lines 2..N+1: Each line contains two space-separated integers describing a fuel stop: The first integer is the distance from the town to the stop; the second is the amount of fuel available at that stop. * Line N+2: Two space-separated integers, L and P

    第1行:一个整数N.
    第2到N+1行:每行有两个用空格隔开的整数,描述一个加油站.第一个数表示这个加油站离城市的距离,第二个数表示在这个加油站最多可以加多少油.
    第N+1行:两个用空格分开的整数L和P.

Output

* Line 1: A single integer giving the minimum number of fuel stops necessary to reach the town. If it is not possible to reach the town, output -1.

 
    一个表示卡车到城市最少要停的次数,如果无法到达输出-1.

Sample Input

4
4 4
5 2
11 5
15 10
25 10

INPUT DETAILS:

The truck is 25 units away from the town; the truck has 10 units
of fuel. Along the road, there are 4 fuel stops at distances 4,
5, 11, and 15 from the town (so these are initially at distances
21, 20, 14, and 10 from the truck). These fuel stops can supply
up to 4, 2, 5, and 10 units of fuel, respectively.

Sample Output

2

现在卡车离城市25个单位,卡车里有10个单位的油.在路上,有4个加油站,分别距离城市4,5,11,15,分别距离卡车则为21,20,14,10.这些加油站分别最多可加油4,2,5,10个单位.开10个单位,加满油10单位油,在开4个单位,加满5单位的油,接着直接开到城市

HINT

Source



好久之前做的贪心了……
还是用P打的……
其实这个贪心还是比较简单的。。。

根据现在的油量,单步最优决策是:
1.能够到达下一个油站或者终点。
2.在能够到达的油站内,加过油后能够扩展的距离最远。
可以简单证明这个贪心的正确性。
所以就水过了= =

好吧
不重打了。。
直接把P交了。。
然后惯例就CE了一次。

var n,i,L,P,ans,max,maxi:longint;
    d,o,f:array[0..10001] of longint;
procedure qsort(l,r:longint);
var i,j,m,t:longint;
begin
  i:=l; j:=r;
  m:=d[(l+r) div 2];
  repeat
    while d[i]<m do inc(i);
    while d[j]>m do dec(j);
    if i<=j then
    begin
      t:=d[i]; d[i]:=d[j]; d[j]:=t;
      t:=o[i]; o[i]:=o[j]; o[j]:=t;
      inc(i); dec(j);
    end;
  until i>j;
  if i<r then qsort(i,r);
  if l<j then qsort(l,j);
end;
begin
  readln(n);
  for i:=1 to n do
    readln(d[i],o[i]);
  readln(L,P);
  for i:=1 to n do
    d[i]:=L-d[i];
  qsort(1,n);
  if P>=L then
  begin
    writeln('0');
    halt;
  end;
  while P<L do
  begin
    max:=0; maxi:=0;
    for i:=1 to n do
    begin
      if f[i]=1 then continue;
      if d[i]>P then break;
      if (d[i]<=P) then
        if max<o[i] then
        begin
          max:=o[i];
          maxi:=i;
        end;
    end;
    f[maxi]:=1;
    P:=P+max;
    inc(ans);
    if maxi=0 then
    begin
      writeln('-1');
      halt;
    end;
  end;
  writeln(ans);
end.

题目描述 牛牛和她的朋友们正在玩一个有趣的游戏,他们需要构建一个有 $n$ 个节点的无向图,每个节点都有一个唯一的编号并且编号从 $1$ 到 $n$。他们需要从节点 $1$ 到节点 $n$ 找到一条最短路径,其中路径长度是经过的边权的和。为了让游戏更有趣,他们决定在图上添加一些额外的边,这些边的权值都是 $x$。他们想知道,如果他们添加的边数尽可能少,最短路径的长度最多会增加多少。 输入格式 第一行包含两个正整数 $n$ 和 $m$,表示节点数和边数。 接下来 $m$ 行,每行包含三个整数 $u_i,v_i,w_i$,表示一条无向边 $(u_i,v_i)$,权值为 $w_i$。 输出格式 输出一个整数,表示最短路径的长度最多会增加多少。 数据范围 $2 \leq n \leq 200$ $1 \leq m \leq n(n-1)/2$ $1 \leq w_i \leq 10^6$ 输入样例 #1: 4 4 1 2 2 2 3 3 3 4 4 4 1 5 输出样例 #1: 5 输入样例 #2: 4 3 1 2 1 2 3 2 3 4 3 输出样例 #2: 2 算法 (BFS+最短路) $O(n^3)$ 我们把问题转化一下,假设原图中没有添加边,所求的就是点 $1$ 到点 $n$ 的最短路,并且我们已经求出了这个最短路的长度 $dis$。 接下来我们从小到大枚举边权 $x$,每次将 $x$ 加入图中,然后再次求解点 $1$ 到点 $n$ 的最短路 $dis'$,那么增加的最短路长度就是 $dis'-dis$。 我们发现,每次加入一个边都需要重新求解最短路。如果我们使用 Dijkstra 算法的话,每次加入一条边需要 $O(m\log m)$ 的时间复杂度,总的时间复杂度就是 $O(m^2\log m)$,无法通过本题。因此我们需要使用更优秀的算法。 观察到 $n$ 的范围比较小,我们可以考虑使用 BFS 求解最短路。如果边权均为 $1$,那么 BFS 可以在 $O(m)$ 的时间复杂度内求解最短路。那么如果我们只是加入了一条边的话,我们可以将边权为 $x$ 的边看做 $x$ 条边的组合,每次加入该边时,我们就在原始图上添加 $x$ 条边,边权均为 $1$。这样,我们就可以使用一次 BFS 求解最短路了。 但是,我们不得不考虑加入多条边的情况。如果我们还是将边权为 $x$ 的边看做 $x$ 条边的组合,那么我们就需要加入 $x$ 条边,而不是一条边。这样,我们就不能使用 BFS 了。 但是,我们可以使用 Floyd 算法。事实上,我们每次加入边时,只有边权等于 $x$ 的边会发生变化。因此,如果我们枚举边权 $x$ 时,每次只需要将边权等于 $x$ 的边加入图中,然后使用 Floyd 算法重新计算最短路即可。由于 Floyd 算法的时间复杂度为 $O(n^3)$,因此总的时间复杂度为 $O(n^4)$。 时间复杂度 $O(n^4)$ 空间复杂度 $O(n^2)$ C++ 代码 注意点:Floyd算法计算任意两点之间的最短路径,只需要在之前的路径基础上加入新的边构成的新路径进行更新即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值