【CF739E】Gosha is hunting(动态规划,凸优化)

【CF739E】Gosha is hunting(动态规划,凸优化)

题面

洛谷
CF

题解

一个\(O(n^3)\)\(dp\)很容易写出来。
我们设\(f[i][a][b]\)表示前\(i\)个怪,两种球用了\(a,b\)个的最大期望,
直接用概率转移就好了。然而这样子会TLE飞。
发现可以凸优化,对于其中一个球给它二分一个权值,表示每使用一次就需要额外花费掉这么多的权值,同时不再限制使用的个数。
然后忽略这一个限制,做\(dp\),利用最优解使用的这种球的个数以及限制个数继续二分。
两维都可以这么做,复杂度\(O(nlog^2)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 2020
#define eps 1e-8
#define cmax(x,y) (x=(x<y?y:x))
double p[MAX],u[MAX];
double f[MAX],fa[MAX],fb[MAX];
int n,a,b;
void Calc(double w1,double w2)
{
	for(int i=1;i<=n;++i)
	{
		f[i]=f[i-1];fa[i]=fa[i-1];fb[i]=fb[i-1];
		if(f[i-1]+p[i]-w1>f[i])
			f[i]=f[i-1]+p[i]-w1,fa[i]=fa[i-1]+1,fb[i]=fb[i-1];
		if(f[i-1]+u[i]-w2>f[i])
			f[i]=f[i-1]+u[i]-w2,fa[i]=fa[i-1],fb[i]=fb[i-1]+1;
		if(f[i-1]+p[i]+u[i]-p[i]*u[i]-w1-w2>f[i])
			f[i]=f[i-1]+p[i]+u[i]-p[i]*u[i]-w1-w2,fa[i]=fa[i-1]+1,fb[i]=fb[i-1]+1;
	}
}
int main()
{
	scanf("%d%d%d",&n,&a,&b);
	for(int i=1;i<=n;++i)scanf("%lf",&p[i]);
	for(int i=1;i<=n;++i)scanf("%lf",&u[i]);
	double l1=0,r1=1,l2,r2;
	while(l1+eps<=r1)
	{
		double mid1=(l1+r1)/2;
		l2=0;r2=1;
		while(l2+eps<=r2)
		{
			double mid2=(l2+r2)/2;
			Calc(mid1,mid2);
			if(fb[n]>b)l2=mid2;else r2=mid2;
		}
		Calc(mid1,r2);
		if(fa[n]>a)l1=mid1;else r1=mid1;
	}
	Calc(r1,r2);
	printf("%.6lf\n",f[n]+a*r1+b*r2);
	return 0;
}
	

posted @ 2018-08-06 08:59  小蒟蒻yyb  阅读(717)  评论(0编辑  收藏  举报