[CF739E]Gosha is hunting
description
你的面前有\(n\)只迪莫,你有\(A\)个大师球和\(B\)个国王球可以用来捕捉这些迪莫。
用大师球捕捉第\(i\)只迪莫的成功概率是\(u_i\),用国王球捕捉第\(i\)只迪莫的成功概率是\(v_i\)。
(不过好像国王球的捕捉成功概率是100%?)
对于每一只迪莫,你不可以使用同种咕噜球超过一次,但你可以同时使用大师球和国王球,两种都成功了的话只算捕捉到一只迪莫。
求你在期望意义下最多可以捕捉到多少只迪莫。
\(n \le 2000,0 \le A,B \le n\)
sol
有一个\(O(n^3)\)的\(dp\):设\(f_{i,j,k}\)表示前\(i\)只迪莫,使用了\(j\)个大师球和\(k\)个国王球的答案。
转移的话直接枚举第\(i\)只迪莫的捕捉方式即可。
然后
直接凸优化套凸优化就可以做到\(O(n\log^2w)\)了。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 2005;
const double eps = 1e-8;
struct info{
double f;int a,b;
bool operator < (const info &x) const{
if (f!=x.f) return f<x.f;
if (b!=x.b) return b>x.b;
return a>x.a;
}
info operator + (const info &x) const
{return (info){f+x.f,a+x.a,b+x.b};}
}dp[N];
int n,A,B;double u[N],v[N];
inline void upt(info &x,info y){if (x<y) x=y;}
void solve(double ca,double cb){
dp[0]=(info){0,0,0};
for (int i=1;i<=n;++i){
dp[i]=dp[i-1];
upt(dp[i],dp[i-1]+(info){u[i]-ca,1,0});
upt(dp[i],dp[i-1]+(info){v[i]-cb,0,1});
upt(dp[i],dp[i-1]+(info){u[i]+v[i]-u[i]*v[i]-ca-cb,1,1});
}
}
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]);
double L=0,R=1,l,r,M,m;
while (R-L>eps){
M=(L+R)/2;l=0;r=1;
while (r-l>eps){
m=(l+r)/2;solve(M,m);
if (dp[n].b<=B) r=m;else l=m;
}
solve(M,r);
if (dp[n].a<=A) R=M;else L=M;
}
solve(R,r);
printf("%.4lf\n",dp[n].f+R*A+r*B);
return 0;
}