Description
给出m种物品,第
Input
第一行两个整数
(1≤n,m≤1000,∑ki≤1000,1≤vali,j≤109)
Output
输出取到最大价值和的概率
Sample Input
3 1
3 10 20 30
Sample Output
1.000000000
Solution
所有物品中价值最大的一些物品肯定要拿,假设从第i种物品中必须拿
Code
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=1005;
ld C[maxn][maxn],dp[maxn][maxn];
int n,m,size[maxn],a[maxn],b[maxn];
P val[maxn];
void init(int n=1000)
{
C[0][0]=1;
for(int i=1;i<=n;i++)
{
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
bool cmp(P x,P y)
{
if(x.first!=y.first)return x.first>y.first;
return x.second<y.second;
}
int main()
{
init();
scanf("%d%d",&n,&m);
int tot=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&size[i]);
for(int j=1;j<=size[i];j++)
{
int temp;
scanf("%d",&temp);
val[tot++]=P(temp,i);
}
}
sort(val,val+tot,cmp);
int num=0,res=0;
for(int i=0;i<tot;)
{
int j=i;
while(j<tot-1&&val[j].first==val[j+1].first)j++;
if(j<n)
while(i<=j)a[val[i++].second]++;
else
{
num=j-i+1,res=n-i;
while(i<=j)b[val[i++].second]++;
break;
}
if(i>=n)break;
}
dp[0][0]=1.0;
for(int i=1;i<=m;i++)dp[0][0]/=C[size[i]][a[i]];
for(int i=1;i<=m;i++)
for(int j=0;j<=res;j++)
{
dp[i][j]=dp[i-1][j];
if(b[i]&&j)dp[i][j]+=dp[i-1][j-1]*(a[i]+1)/(size[i]-a[i]);
}
cout<<fixed<<setprecision(10)<<dp[m][res]/C[num][res]<<endl;
return 0;
}