[CF739E]Gosha is hunting

codeforces

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;
}
posted @ 2018-08-06 10:33  租酥雨  阅读(190)  评论(0编辑  收藏  举报