期望DP
很神的DP。
如果直接考虑每一轮用掉了什么东西,对下一轮产生了什么影响,那基本是做不出来的,因为这之间的关系很多很复杂。
注意到一个物品至多被某一轮选一次。考虑所有轮一起做,记f[i][j]表示做到第i个物品时还有j轮没有选完。那么i此时可以在这j轮中被选,也可以不被选,就可以DP了。这种DP就可以避免物品与物品之间的影响了。
#include<cstdio>
#include<cstring>
#define N 233
#define R 140
#define ld long double
using namespace std;
namespace runzhe2000
{
ld f[N][R], p[N], pow[N][R], ans;
int d[N];
void main()
{
int T; scanf("%d",&T);
for(int n, r; T--; )
{
scanf("%d%d",&n,&r);
for(int i = 1; i <= n; i++)
{
scanf("%Lf%d",&p[i],&d[i]);
pow[i][0] = 1;
for(int j = 1; j <= r; j++)
pow[i][j] = pow[i][j-1] * (1 - p[i]);
}
for(int i = 0; i < R; i++) f[0][i] = 0;
f[0][r] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= r; j++)
f[i][j] = f[i-1][j] * pow[i][j] + f[i-1][j+1] * (1 - pow[i][j+1]);
for(int j = r+1; j < R; j++) f[i][j] = 0;
}
ans = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= r; j++)
ans += d[i] * f[i-1][j] * (1 - pow[i][j]);
printf("%.10Lf\n",ans);
}
}
}
int main()
{
runzhe2000::main();
}