官方题解是一个n2logn的dp做法
不过有一个简单易想的费用流做法
对每个小精灵,连边(A,i,1,pi) (B,i,1,ui) (i,t,1,0) (i,t,1,-pi*ui)
最后连边(s,A,a,0) (s,B,b,0)
跑最大费用最大流即可,注意精度误差

1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 struct way{int po,next,flow;double cost;} e[40010]; 6 const double eps=1e-8; 7 int pre[2010],p[2010],cur[2010],q[4000010]; 8 double d[2010],c[2010]; 9 bool v[2010]; 10 int len,n,m,a,b,t; 11 12 void add(int x,int y,int f,double c) 13 { 14 e[++len].po=y; 15 e[len].flow=f; 16 e[len].cost=c; 17 e[len].next=p[x]; 18 p[x]=len; 19 } 20 21 void build(int x,int y,int f,double c) 22 { 23 add(x,y,f,c); 24 add(y,x,0,-c); 25 } 26 27 bool spfa() 28 { 29 for (int i=1; i<=t; i++) d[i]=-1e20; 30 memset(v,0,sizeof(v)); 31 d[0]=0; 32 int f=1,r=1;q[1]=0; 33 while (f<=r) 34 { 35 int x=q[f++]; 36 v[x]=0; 37 for (int i=p[x]; i!=-1; i=e[i].next) 38 { 39 int y=e[i].po; 40 if (e[i].flow&&d[x]+e[i].cost-eps>d[y]) 41 { 42 d[y]=d[x]+e[i].cost; 43 pre[y]=x; cur[y]=i; 44 if (!v[y]) 45 { 46 q[++r]=y; 47 v[y]=1; 48 } 49 } 50 } 51 } 52 return d[t]>-1e20; 53 } 54 55 double cost() 56 { 57 double s=0; 58 while (spfa()) 59 { 60 s+=d[t]; 61 for (int i=t; i; i=pre[i]) 62 { 63 int j=cur[i]; 64 e[j].flow--; 65 e[j^1].flow++; 66 } 67 } 68 return s; 69 } 70 71 int main() 72 { 73 len=-1; 74 memset(p,255,sizeof(p)); 75 scanf("%d%d%d",&n,&a,&b); 76 t=n+3; 77 for (int i=1; i<=n; i++) 78 { 79 scanf("%lf",&c[i]); 80 build(n+1,i,1,c[i]); 81 build(i,t,1,0); 82 } 83 for (int i=1; i<=n; i++) 84 { 85 double x; 86 scanf("%lf",&x); 87 build(n+2,i,1,x); 88 build(i,t,1,-c[i]*x); 89 } 90 build(0,n+1,a,0); 91 build(0,n+2,b,0); 92 printf("%.5lf ",cost()); 93 }