zoukankan      html  css  js  c++  java
  • E. Gosha is hunting (dp + wqs套wqs)

    E. Gosha is hunting
    time limit per test
    5 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Gosha is hunting. His goal is to catch as many Pokemons as possible. Gosha has a Poke Balls and b Ultra Balls. There are nPokemons. They are numbered 1 through n. Gosha knows that if he throws a Poke Ball at the i-th Pokemon he catches it with probability pi. If he throws an Ultra Ball at the i-th Pokemon he catches it with probability ui. He can throw at most one Ball of each type at any Pokemon.

    The hunting proceeds as follows: at first, Gosha chooses no more than a Pokemons at which he will throw Poke Balls and no more than b Pokemons at which he will throw Ultra Balls. After that, he throws the chosen Balls at the chosen Pokemons. If he throws both Ultra Ball and Poke Ball at some Pokemon, he is caught if and only if he is caught by any of these Balls. The outcome of a throw doesn't depend on the other throws.

    Gosha would like to know what is the expected number of the Pokemons he catches if he acts in an optimal way. In other words, he would like to know the maximum possible expected number of Pokemons can catch.

    Input

    The first line contains three integers na and b (2 ≤ n ≤ 2000, 0 ≤ a, b ≤ n) — the number of Pokemons, the number of Poke Balls and the number of Ultra Balls.

    The second line contains n real values p1, p2, ..., pn (0 ≤ pi ≤ 1), where pi is the probability of catching the i-th Pokemon if Gosha throws a Poke Ball to it.

    The third line contains n real values u1, u2, ..., un (0 ≤ ui ≤ 1), where ui is the probability of catching the i-th Pokemon if Gosha throws an Ultra Ball to it.

    All the probabilities are given with exactly three digits after the decimal separator.

    Output

    Print the maximum possible expected number of Pokemons Gosha can catch. The answer is considered correct if it's absolute or relative error doesn't exceed 10 - 4.

    Examples
    input
    Copy
    3 2 2
    1.000 0.000 0.500
    0.000 1.000 0.500
    output
    Copy
    2.75
    input
    Copy
    4 1 3
    0.100 0.500 0.500 0.600
    0.100 0.500 0.900 0.400
    output
    Copy
    2.16
    input
    Copy
    3 2 0
    0.412 0.198 0.599
    0.612 0.987 0.443
    output
    Copy
    1.011


    SOLUTION:

    首先要优化状态,因为它本身三维状态。

    我们试着不考虑a的限制,设状态dp_{i,j}dpi,j表示前i个神奇宝贝,使用j个超级球和若干精灵球的最大期望。

    但是这样可能会多用一些精灵球。于是我们假设每次使用一个精灵球,需要花费一个代价caca,并在dp时记录精灵球的用量,设为uaua。那么实际期望就是dp_{i,b}+ua_n imes cadpi,b+uan×ca。

    那么如何使它刚好使用a个精灵球呢?

    发现精灵球用量随ca的增加而不增(不一定降)。

    没错,二分ca。

    于是,复杂度从O(n^3)O(n3)下降为O(n^2logn)O(n2logn),已经可以过了。

    这就是wqs二分,二分一个附加费用使某一物品的使用量发生变化。

    但是还可以优化。

    既然a这一维可以被省略,b这一维为什么不可以呢?

    于是我们用同样的方法设dp_idpi为前i只神奇宝贝,使用若干精灵球和超级球的期望,二分使用超级球的代价cbcb并记录dp过程中超级球的使用量ubub。

    那么,实际代价就是dp_n+ua_n imes ca+ub_n imes cbdpn+uan×ca+ubn×cb

     

    CODE:

    
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define T 60
    #define N 2010
    using namespace std;
    typedef double LD;
    const LD INF = 1e5;
    
    LD u[N], v[N], q[N], L, R;
    int n, a, b;
    
    struct Node{
        LD val;
        int a, b;
        Node(LD V = 0, int A = 0, int B = 0) {
            val = V; a = A; b = B;
        }
        inline bool operator < (const Node &o) const {
            return val < o.val;
        }
        inline Node operator + (const Node &o) const {
            return Node(val + o.val, a + o.a, b + o.b);
        }
    }dp[N];
    
    inline void check_agn(LD x, LD y) {
        dp[0] = Node();
        for (int i = 1; i <= n; ++i) {
            dp[i] = Node(-INF, 0, 0);
            dp[i] = max(max(dp[i - 1], dp[i - 1] + Node(q[i] - x - y, 1, 1)), max(dp[i - 1] + Node(u[i] - x, 1, 0), dp[i - 1] + Node(v[i] - y, 0, 1)));
        }
    }
    
    inline void check(LD v) {
        L = 0, R = 1;
        for (int i = 1; i <= T; ++i) {
            LD mid = (L + R) / 2;
            check_agn(v, mid);
            if (dp[n].b >= b) L = mid;
            else R = mid;
        }
        check_agn(v, L);
    }
    
    int main() {
        scanf("%d%d%d", &n, &a, &b);
        for (int i = 1; i <= n; ++i) {
            scanf("%lf", &u[i]);
        }
        for (int i = 1; i <= n; ++i) {
            scanf("%lf", &v[i]);
        }
        for (int i = 1; i <= n; ++i) {
            q[i] = u[i] + v[i] - u[i] * v[i];
        }
        LD l = -1000, r = 1000;
        for (int i = 1; i <= T; ++i) {
            LD mid = (l + r) / 2;
            check(mid);
            if (dp[n].a >= a) l = mid;
            else r = mid;
        }
        check(l);
    //  printf("%.5Lf %.5Lf
     %d %d 
    ", l, L, dp[n].a, dp[n].b);
        printf("%.5lf
    ", dp[n].val + l * a + L * b);
        return 0;
    }
    
    
    

      





  • 相关阅读:
    codesmith+mysql生成代码
    遭遇笔试
    线性是一种简洁,简洁就是美
    Microsoft Kinect SDK vs PrimeSense OpenNI
    资料收集:让OpenCV使用IPP
    提纲
    在PC上安装使用Kinect
    OpenNI设置Kinect帧率,读取IR图
    cout,rather than printf
    单步调试时,getnextframe会失败。又
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11242443.html
Copyright © 2011-2022 走看看