Codeforces 749E Gosha is hunting 二分+DP

Posted tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 749E Gosha is hunting 二分+DP相关的知识,希望对你有一定的参考价值。

很神奇的一题 看完题解不由惊叹

题意:$n$个神奇宝贝 $a$个普通球 $b$个高级球 普通球抓住$i$神奇宝贝的概率为$u[i]$ 高级球为$p[i]$ 一起用为$u[i]+p[i]-u[i]*p[i]$ 求期望抓到个神奇宝贝个数

$N,a,b\leq2000$

首先不难想到$O(n^3)$的暴力$DP$ 听说CF的机子可过 我们接下来写如何优化

对于一个凸函数$f(x)$ 我们假设可以通过某种特殊方式获得其的极值和极值点

令$F(x)=f(x)-kx$ 不难发现$F(x)$也是一个凸函数 仍然假设可以获得其极值和极值点 那么求导可以看出 当$k$减小时 极值点会右移

对于本题 暴力的$dp$ 为$f[i][j][k]$ 表示到第$i$个神奇宝贝用了$j$个普通球 $k$个高级球的最大期望

我们可以发现如果将$f[i][j](x)$看做之前提到的$f(x)$ 那么我们可以通过二分$k$值并不断更新 使得$F(x)$ 的极值点为$b$ 此时的$ans=F[n][a]_{max}+b*k$ 即为最大值

对于一次求$F(x)=f[n][a]-kx$的时间复杂度为$O(n^2)$

#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi first
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
#define eps 1e-10
const int INF = 0x3fff;
const int N=2e3+5;
/*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
    int x=0,rev=0,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return rev?-x:x;
}
double f[N][N],u[N],p[N];
int n,a,b,g[N][N];
void update(double&a,int&b,double c,int d){
    if(a+eps<c) a=c,b=d; 
}
int calc(double k){
    for(int i=1;i<=n;i++)
        for(int j=0;j<=a;j++){
        f[i][j]=g[i][j]=0;
        update(f[i][j],g[i][j],f[i-1][j],g[i-1][j]);
        update(f[i][j],g[i][j],f[i-1][j]+u[i]-k,g[i-1][j]+1);
        if(!j)continue;
        update(f[i][j],g[i][j],f[i-1][j-1]+p[i],g[i-1][j-1]);
        update(f[i][j],g[i][j],f[i-1][j-1]+1-(1-p[i])*(1-u[i])-k,g[i-1][j-1]+1);
    }
    return g[n][a];
}
int main(){
#ifdef Devil_Gary
    freopen("in.txt","r",stdin);
#endif
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++) cin>>p[i]; 
    for(int i=1;i<=n;i++) cin>>u[i]; 
    double l=-INF,r=INF;
    for(int T=1;T<=100;T++){
        double mid=(l+r)/2; 
        if(calc(mid)<=b) r=mid;
        else l=mid;
    } 
    return printf("%.8f\n",f[n][a]+b*l),0;
}

以上是关于Codeforces 749E Gosha is hunting 二分+DP的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces739E Gosha is hunting

Codeforces Round #381 (Div. 1) E - Gosha is hunting 最大费用网络流 期望

Codeforces.739E.Gosha is hunting(DP 带权二分)

CodeForces 749E: Inversions After Shuffle

codeforces 749E Inversions After Shuffle

Inversions After Shuffle CodeForces - 749E (概率,期望)