题解 CF739E 【Gosha is hunting】
由于刚学带权二分,所以考虑带权二分
对于dp优化型题目,首先写出普通dp方程,
我们发现一只宝可梦用一只球会比两只球有性价比(毕竟还要减
所以当
这里就有一个针对凸函数的办法:引一条直线使该直线与函数相切,这个函数也是由一小节一小节线段构成的(毕竟大家都是整数),当相切时实际上引的直线就是那一条线段比如:
而我们想要得到的是在正确函数上当口胡设一个函数
这就是我们拿来还原图像的直线(
这下我们表示出了截距,我们要想办法让截距最大
发现
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define ld double
#define mid ((l+r)/2)
using namespace std;
ll n,a,b;
ld p[10001],q[10001],f[2010][2010],cnt[2101][2101];
bool check_dp(ld sam);
int main(){
scanf("%lld%lld%lld",&n,&a,&b);
for(ll i=1;i<=n;i++)scanf("%lf",&p[i]);
for(ll i=1;i<=n;i++)scanf("%lf",&q[i]);
ld l=0,r=1,ans=1;
for(ll o=1;o<=60;o++){
if(check_dp(mid))ans=mid,r=mid-1;
else l=mid+1;
}
ans=f[n][a]+ans*b;
printf("%.5lf\n",ans);
}
bool check_dp(ld sam){
memset(f,0,sizeof f);
memset(cnt,0,sizeof cnt);
ll i,j;
for(i=1;i<=n;i++){
for(j=0;j<=a;j++){
cnt[i][j]=cnt[i-1][j];
f[i][j]=f[i-1][j];
if(j!=0&&f[i-1][j-1]+p[i]>f[i][j]){
cnt[i][j]=cnt[i-1][j-1];
f[i][j]=p[i]+f[i-1][j-1];
}
if(f[i-1][j]+q[i]-sam>f[i][j]){
cnt[i][j]=cnt[i-1][j]+1;
f[i][j]=f[i-1][j]+q[i]-sam;
}
if(j!=0&&f[i-1][j-1]+p[i]+q[i]-q[i]*p[i]-sam>f[i][j]){
cnt[i][j]=cnt[i-1][j-1]+1;
f[i][j]=f[i-1][j-1]+p[i]+q[i]-q[i]*p[i]-sam;
}
}
}
return cnt[n][a]<=b;
}