zoukankan      html  css  js  c++  java
  • USACO 2013 Nov Silver Pogo-Cow

    最近因为闲的蛋疼(停课了),所以开始做一些 USACO 的银组题。被完虐啊 TAT

    貌似 Pogo-Cow 这题是 2013 Nov Silver 唯一一道可说的题目?

    Pogo-Cow

    • Description

    (大意是一条直线上有一些带权值的点,可以选择一个点作为出发点,选好一个前进方向(左或右)然后不断地向前跳到另一个点,得分为这个点的权值,要求每一跳的跳跃距离不小于前一跳,求能获得的最大得分)

    In an ill-conceived attempt to enhance the mobility of his prize cow
    Bessie, Farmer John has attached a pogo stick to each of Bessie's legs. 
    Bessie can now hop around quickly throughout the farm, but she has not yet
    learned how to slow down.

    To help train Bessie to hop with greater control, Farmer John sets up a
    practice course for her along a straight one-dimensional path across his
    farm. At various distinct positions on the path, he places N targets on
    which Bessie should try to land (1 <= N <= 1000). Target i is located at
    position x(i), and is worth p(i) points if Bessie lands on it. Bessie
    starts at the location of any target of her choosing and is allowed to move
    in only one direction, hopping from target to target. Each hop must cover
    at least as much distance as the previous hop, and must land on a target.

    Bessie receives credit for every target she touches (including the initial
    target on which she starts). Please compute the maximum number of points
    she can obtain.

    • Solution

    想了好一会儿,到晚自习下课的时候想到了算法,然后回寝室冷静了一个晚上,第二天实现了一下。

    先只考虑一个方向上的。(另一个方向的话只要反向做一遍就好了)

    首先,肯定要先按照横坐标将这些点排序。

    其实 O(N^3) 的 DP 是不难想到的:用 f(i, j) 表示从 i 跳到 j 再往后跳的最大得分(因为只考虑单方向所以假设 j > i),则

    f(i, j) = w(i)+max{ f(j, k) }, k>j 且 x(k)-x(j) >= x(j)-x(i)

    w(i) 表示第 i 个点的权值。

    然后优化:

    对于上面方程中的 k,我们只要找到第一个满足条件的 k 就会发现 k+1, k+2, ..., n 都是满足条件的。

    那么我们干脆维护一个区间最大值:用 m(i, j) 表示 max{ f(i, j), f(i, j+1), ..., f(i, n) }

    于是上面的方程就可以改写成:

    f(i, j) = w(i)+m(j, k), k>j 且 k 是满足条件 x(k)-x(j) >= x(j)-x(i) 的第一个点

    显然我们可以用二分查找来找到这个 k。

    至于 m(i, j) 的维护,因为 k 在 j 的后面所以我们是倒着来 DP(i 和 j 逆序枚举),那么得到一个 f(i, j) 之后就可以更新 m(i, j) 的值了:

    m(i, j) = max{ f(i, j), m(i, j+1) }

    至此,问题的复杂度降为 O(N2logN)。

     

    这种方法其实是很普遍的,比如下面这道同样是 USACO Silver 题:

    POJ 3616 Milking Time

    Description

    Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that she decides to schedule her next N (1 ≤ N ≤ 1,000,000) hours (conveniently labeled 0..N-1) so that she produces as much milk as possible.

    Farmer John has a list of M (1 ≤ M ≤ 1,000) possibly overlapping intervals in which he is available for milking. Each interval i has a starting hour (0 ≤ starting_houri ≤ N), an ending hour (starting_houri < ending_houri ≤ N), and a corresponding efficiency (1 ≤ efficiencyi ≤ 1,000,000) which indicates how many gallons of milk that he can get out of Bessie in that interval. Farmer John starts and stops milking at the beginning of the starting hour and ending hour, respectively. When being milked, Bessie must be milked through an entire interval.

    Even Bessie has her limitations, though. After being milked during any interval, she must rest R (1 ≤ R ≤ N) hours before she can start milking again. Given Farmer Johns list of intervals, determine the maximum amount of milk that Bessie can produce in the N hours.

    Input

    * Line 1: Three space-separated integers: NM, and R
    * Lines 2..M+1: Line i+1 describes FJ's ith milking interval withthree space-separated integers: starting_houri , ending_houri , and efficiencyi

    Output

    * Line 1: The maximum number of gallons of milk that Bessie can product in the N hours

    Sample Input

    12 4 2

    1 2 8

    10 12 19

    3 6 24

    7 10 31

    Sample Output

    43

    Source

    USACO 2007 November Silver

     

    题目大意是有 M 个可能有重叠的时间段,每个时间段有不同的收益,选出一些时间段满足前一个时间段的结束时刻到后一个时间段的开始时刻至少有 R 的间隔时间,求能达到的最大收益。

    其实这道题完全可以用平方级的算法操过去,但是本着闲着蛋疼就来折腾 POJ 服务器的原则,我们可以用上述方法优化到 O(NlogN):(当然先把区间按照结束时间排序)用 f(i) 表示最后一个区间是第 i 个的时候所能得到的最大收益,则

    f(i) = w(i)+max{ f(k) }, k<i 且 end_time(k)+R<=start_time(i)

    然后用上面的方法二分找到第一个满足条件的 k,并维护一个连续区间的最大值。注意这次应该正着来(因为要找的 k 在i 前面嘛)。

    应 LZW 大神要求写得更详细一些:

    令 m(i) = max{ f(1), f(2), ..., f(i-1), f(i) },则动规方程可以改为:

    f(i) = w(i)+m(k), k<i 且 k 是满足条件 end_time(k)+R<=start_time(i) 的最靠后的时间段

    同样地,m(i) 在得到一个 f(i) 之后维护:

    m(i) = max{ f(i), m(i-1) }

    (但是时间上和 LZW 大神的平方算法一样啊,给常数小得人神共怒的 LZW 大牛跪了)

    (估计 ZBT 大神会吐槽我:「就这两个破题目你也要写篇题解?」)

  • 相关阅读:
    JAVA-初步认识-第九章-抽象类-特点
    JAVA-初步认识-第九章-抽象类-概述
    JAVA-初步认识-第九章-面向对象-final关键字
    JAVA-初步认识-第九章-继承-子父类中的构造函数-子类的实例化过程-内存图解
    JAVA-初步认识-第九章-继承-子父类中的构造函数-子类的实例化过程-细节
    JAVA-初步认识-第九章-继承-子父类中的构造函数-子类的实例化过程
    JAVA-初步认识-第八章-继承-子父类中成员变量的特点-覆盖的应用
    JAVA-初步认识-第八章-继承-子父类中成员函数特点-覆盖
    JAVA-初步认识-第八章-继承-子父类中成员变量的内存图解
    JAVA-初步认识-第八章-继承-子父类中成员变量的特点
  • 原文地址:https://www.cnblogs.com/lsdsjy/p/pogo-cow.html
Copyright © 2011-2022 走看看