题目链接:https://codeforces.com/contest/739/problem/E
凸优化经典题
凸优化:
指有若干个物品,要求选出 (m) 个,选的时候带有限制,求最优的方案。
这种题的特点是:如果不限制选的个数,很容易就能求出最优方案。
使用凸优化的条件:设 (f(i)) 为选 (i) 个物品的最优方案,则 (f(i)) 是关于 (i) 的凸函数
对于该题:很容易想到 (O(n^3)) 的(dp), (dp[i][j][k]) 表示捕捉前 (i) 个精灵,用了 (j) 个宝贝球,(k) 个超级球的最大期望
转移讨论四种情况即可
可以发现,(j,k) 两维都是凸的,即选的越多期望越大,于是两维都可以使用凸优化
时间复杂度 (O(nlog^2n))
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 2010;
const double eps = 1e-8;
int n, a, b;
double p[maxn], u[maxn];
double dp[maxn][maxn];
int g[maxn][maxn];
bool check(double x){
memset(dp, 0, sizeof(dp));
memset(g, 0, sizeof(g));
for(int i = 1 ; i <= n ; ++i){
for(int j = 0 ; j <= a ; ++j){
dp[i][j] = max(dp[i][j], dp[i-1][j]);
g[i][j] = g[i-1][j];
if(j >= 1){
if(dp[i-1][j-1] + p[i] - dp[i][j] > eps){
dp[i][j] = max(dp[i][j], dp[i-1][j-1] + p[i]);
g[i][j] = g[i-1][j-1];
}
}
if(dp[i-1][j] + u[i] - x - dp[i][j] > eps){
dp[i][j] = max(dp[i][j], dp[i-1][j] + u[i] - x);
g[i][j] = g[i-1][j] + 1;
}
if(j >= 1) {
if(dp[i-1][j-1] + p[i] + u[i] - u[i] * p[i] - x - dp[i][j] > eps){
dp[i][j] = max(dp[i][j], dp[i-1][j-1] + p[i] + u[i] - u[i] * p[i] - x);
g[i][j] = g[i-1][j-1] + 1;
}
}
}
}
if(g[n][a] >= b) return true;
else return false;
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
n = read(), a = read(), b = read();
for(int i = 1 ; i <= n ; ++i) scanf("%lf", &p[i]);
for(int i = 1 ; i <= n ; ++i) scanf("%lf", &u[i]);
double l = 0, r = 1;
while(r - l > eps){
double mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
}
printf("%.3lf
", dp[n][a] + b * l);
return 0;
}