题意:
- 有
n
个人和m种T-shirt,每个人都有一种喜欢的T-shirt,然而你只知道他们每个人喜欢某种的概率。
- 你需要在开始时选定
n
件T-shirt的种类,人们会按照编号从1~
n
挑选T-shirt,如果剩下还有他喜欢的,则会选走,否则不变。
- 请输出最大的期望送出的T-shirt件数。
- n≤3000,m≤300
题解:
代码:
#include <bits/stdc++.h>
#define N 3009
#define M 309
using namespace std;
int n,m;
long double p[N][M],delta[M],f[M][N],Ans=0.0,last_f[N],number[M];
void work(int now)
{
number[now]++;
if (number[now]>=n)
{
delta[now]=0.0;
return;
}
for (int i=0;i<=n;i++) last_f[i]=f[now][i];
f[now][0]=0.0;
for (int i=1;i<=n;i++)
f[now][i]=f[now][i-1]*(1.0-p[i][now])+last_f[i-1]*p[i][now];
delta[now]-=f[now][n];
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
int x;
cin>>x;
p[i][j]=(long double)x/1000.0;
}
for (int i=1;i<=m;i++)
{
f[i][0]=1.0;
for (int j=1;j<=n;j++)
f[i][j]=f[i][j-1]*(1.0-p[j][i]);
delta[i]=1.0-f[i][n];
}
for (int i=1;i<=n;i++)
{
long double Max=0.0;
int k=0;
for (int j=1;j<=m;j++)
if (delta[j]>Max)
{
Max=delta[j];
k=j;
}
Ans+=Max;
if (!k) break;
work(k);
}
cout<<fixed<<setprecision(10)<<Ans<<endl;
return 0;
}