点此看题面
大致题意: 你有两种捕捉球(分别为
A
A
A个和
B
B
B个),要捕捉
n
n
n个神奇宝贝,第
i
i
i个神奇宝贝被第一种球捕捉的概率是
s
1
i
s1_i
s1i,被第二种球捕捉的概率是
s
2
i
s2_i
s2i,问在最优策略下期望捕捉到的神奇宝贝数量。
W
Q
S
WQS
WQS二分
这应该是一道比较经典的
W
Q
S
WQS
WQS二分题(毕竟是
W
Q
S
WQS
WQS二分套
W
Q
S
WQS
WQS二分)。
L
i
n
k
Link
Link
W
Q
S
WQS
WQS二分 详见博客 WQS二分学习笔记
W
Q
S
WQS
WQS二分套
W
Q
S
WQS
WQS二分
如果你知道
W
Q
S
WQS
WQS二分,应该就不难想到
W
Q
S
WQS
WQS二分一个代价
C
1
C1
C1,表示每使用一个第一种球所需要的代价,然后再
W
Q
S
WQS
WQS二分一个代价
C
2
C2
C2,表示每使用一个第二种球所需要的代价。于是就成了
W
Q
S
WQS
WQS二分套
W
Q
S
WQS
WQS二分。
D
P
DP
DP转移
在
W
Q
S
WQS
WQS二分后,就是
D
P
DP
DP了。
我们可以用
f
i
f_i
fi表示到第
i
i
i个神奇宝贝为止捕捉到的神奇宝贝总数的最大期望值,并用
g
1
i
g1_i
g1i表示此时使用的第一种捕捉球个数,用
g
2
i
g2_i
g2i表示此时使用的第二种捕捉球个数。
其实
D
P
DP
DP也是挺简单的,共有
4
4
4种情况:
不使用捕捉球。
f
i
=
f
i
−
1
,
g
1
i
=
g
1
i
−
1
,
g
2
i
=
g
2
i
−
1
f_i=f_{i-1},g1_i=g1_{i-1},g2_i=g2_{i-1}
fi=fi−1,g1i=g1i−1,g2i=g2i−1。使用第一种捕捉球。
f
i
=
f
i
−
1
+
s
1
i
−
C
1
,
g
1
i
=
g
1
i
−
1
+
1
,
g
2
i
=
g
2
i
−
1
f_i=f_{i-1}+s1_i-C1,g1_i=g1_{i-1}+1,g2_i=g2_{i-1}
fi=fi−1+s1i−C1,g1i=g1i−1+1,g2i=g2i−1使用第二种捕捉球。
f
i
=
f
i
−
1
+
s
2
i
−
C
2
,
g
1
i
=
g
1
i
−
1
,
g
2
i
=
g
2
i
−
1
+
1
f_i=f_{i-1}+s2_i-C2,g1_i=g1_{i-1},g2_i=g2_{i-1}+1
fi=fi−1+s2i−C2,g1i=g1i−1,g2i=g2i−1+1同时使用两种捕捉球。
f
i
=
f
i
−
1
+
s
1
i
+
s
2
i
−
C
1
−
C
2
−
s
1
i
∗
s
2
i
,
g
1
i
=
g
1
i
−
1
+
1
,
g
2
i
=
g
2
i
−
1
+
1
f_i=f_{i-1}+s1_i+s2_i-C1-C2-s1_i*s2_i,g1_i=g1_{i-1}+1,g2_i=g2_{i-1}+1
fi=fi−1+s1i+s2i−C1−C2−s1i∗s2i,g1i=g1i−1+1,g2i=g2i−1+1
这样就可以了。
代码
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define N 100000
#define eps 1e-12
using namespace std
;
int n
,A
,B
;double s1
[N
+5],s2
[N
+5];
class Class_WQS
{
private:
double C1
,C2
,f
[N
+5];int g1
[N
+5],g2
[N
+5];
inline void check()
{
for(register int i
=1;i
<=n
;++i
)
{
f
[i
]=f
[i
-1],g1
[i
]=g1
[i
-1],g2
[i
]=g2
[i
-1];
if(f
[i
-1]+(s1
[i
]-C1
)-f
[i
]>eps
) f
[i
]=f
[i
-1]+(s1
[i
]-C1
),g1
[i
]=g1
[i
-1]+1,g2
[i
]=g2
[i
-1];
if(f
[i
-1]+(s2
[i
]-C2
)-f
[i
]>eps
) f
[i
]=f
[i
-1]+(s2
[i
]-C2
),g1
[i
]=g1
[i
-1],g2
[i
]=g2
[i
-1]+1;
if(f
[i
-1]+(s1
[i
]+s2
[i
]-C1
-C2
-s1
[i
]*s2
[i
])-f
[i
]>eps
) f
[i
]=f
[i
-1]+(s1
[i
]+s2
[i
]-C1
-C2
-s1
[i
]*s2
[i
]),g1
[i
]=g1
[i
-1]+1,g2
[i
]=g2
[i
-1]+1;
}
}
inline void GetRes()
{
register double l
=0.0,r
=1.0;
for(C2
=(l
+r
)/2;r
-l
>eps
;C2
=(l
+r
)/2)
{
if(check(),!(g2
[n
]^B
)) return;
g2
[n
]>B
?l
=C2
:r
=C2
;
}
}
public:
inline double GetAns()
{
register double l
=0.0,r
=1.0;
for(C1
=(l
+r
)/2;r
-l
>eps
;C1
=(l
+r
)/2)
{
if(GetRes(),!(g1
[n
]^A
)) break;
g1
[n
]>A
?l
=C1
:r
=C1
;
}
return f
[n
]+A
*C1
+B
*C2
;
}
}WQS
;
int main()
{
register int i
;
scanf("%d%d%d",&n
,&A
,&B
);
for(i
=1;i
<=n
;++i
) scanf("%lf",&s1
[i
]);
for(i
=1;i
<=n
;++i
) scanf("%lf",&s2
[i
]);
return printf("%.10lf\n",WQS
.GetAns()),0;
}