这题在博客左上角放了好久了,一直不会做,看了半天题解,勉强看懂。。
参考:http://blog.csdn.net/squee_spoon/article/details/52040852
看看各个博客的讲解,看看代码,强行理解。。。我的理解写在注释里了。
#include <bits/stdc++.h>
using namespace std;
double dp[1<<20];
double p[22];
double ans[22];
int bit_cnt[1<<20];
int main()
{
ios::sync_with_stdio(false);
int n,k;
cin>>n>>k;
for(int i=0; i<n; i++)
cin>>p[i];
int limit = 1<<(n);
for(int i=1; i<limit; i++)
bit_cnt[i] = __builtin_popcount(i);
dp[0] = 1;
for(int i=1; i<limit; i++)
{
dp[i] = 0;
double pp = 0;
for(int j=0; j<n; j++)
{
if(i&(1<<j))
{
//从没有这位的状态转移到当前状态
dp[i] += dp[i^(1<<j)] * p[j];
pp += p[j];
}
}
//如果当前状态有k位,就是最终状态,计算答案
if(bit_cnt[i] == k )
{
for(int j=0; j<n; j++)
{
if(i&(1<<j))
ans[j] += dp[i];
}
}
//留下只选择这几个元素的概率
dp[i] /= (1-pp);
}
int cnt = n;
for(int i=0; i<n; i++)
if(p[i] == 0)
cnt--;
if(cnt<k)
{
for(int i=0; i<n; i++)
cout << fixed << setprecision(8) << ((p[i]==0.0)?0.0:1.0) << " ";
}
else
{
for(int i=0; i<n; i++)
cout << fixed << setprecision(8) << ans[i] << " ";
}
return 0;
}