题意:有一个箱子最多装k件物品,现在有n件物品,第i件物品被询问的概率为pi,当第i件物品被询问时,如果第i件物品不在箱子里面,则把第i件物品加入到箱子中,若箱子物品数量>k,则移除最早添加进来的物品.
问10^100次查询后,每个物品在箱子中的概率? n,k<=20.
询问10^100次,物品最多只有20个,所以可以说箱子最后肯定有k个物品
问题转化为求最后状态为S的概率,初始时抽到k种不同物品的状态S'和S一一映射.
问10^100次查询后,每个物品在箱子中的概率? n,k<=20.
询问10^100次,物品最多只有20个,所以可以说箱子最后肯定有k个物品
问题转化为求最后状态为S的概率,初始时抽到k种不同物品的状态S'和S一一映射.
转移状态时合并GS的和得:dp[i|(1<<j)]=dp[i]*p[j]/(1-sum)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=1<<21;
double dp[N],p[21],ans[21];
int n,k;
int main()
{
while(cin>>n>>k)
{
int cnt=0;
for(int i=0;i<n;i++)
{
cin>>p[i];
if(p[i]>0)
cnt++;
}
memset(dp,0,sizeof(dp));
k=min(k,cnt);
dp[0]=1.0;
for(int i=0;i<(1<<n);i++)
{
cnt=0;
double sum=0;
for(int j=0;j<n;j++)
{
if((i>>j)&1)
cnt++,sum+=p[j];
}
for(int j=0;j<n;j++)
{
if(!((i>>j)&1))
dp[i|(1<<j)]+=dp[i]*p[j]/(1.0-sum);
}
if(cnt==k)
{
for(int j=0;j<n;j++)
{
if((i>>j)&1)
ans[j]+=dp[i];
}
}
}
for(int i=0;i<n;i++)
printf("%.10lf ",ans[i]);
printf("\n");
}
return 0;
}