- 有n条鱼,每天会有两条鱼相遇,每天任意两条鱼相遇的概率一样,给出i,j相遇时i吃掉j的概率和j吃掉i的概率,最后池塘中只会留下一条鱼,求最后池塘中留下的每条鱼的概率。n<=18
- 当池塘还剩下cnt 条鱼时,选出还在池塘中的鱼i,j的概率为2/cnt/(cnt-1),i吃掉j的概率为a[i][j];
- 可以考虑对池塘进行状态压缩,n条鱼的池塘看成n为二进制数,设当前状态为s,s中的i吃掉了j,则状态变为s^(1<<(j-1)),因此状态转移方程为f [s^(1<<(j-1))]=f[s]*a[i][j]*2/cnt/(cnt-1);
#include <iostream>
#include <cstdio>
using namespace std;
int n;
double a[20][20],f[1<<19];
int getnum(int s)
{
int ans=0;
for(int i=17;i>=0;i--)
{
if((1<<i)<=s)
{
s-=(1<<i);
ans++;
}
}
return ans;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
f[(1<<n)-1]=1;
for(int i=(1<<n)-1;i>0;i--)
{
if(f[i])
for(int j=1;j<=n;j++)
if(i&(1<<(j-1)))
for(int k=1;k<=n;k++)
if(k!=j&&(i&(1<<(k-1))))
{
int cnt=getnum(i);
if(cnt>0)
f[i^(1<<(k-1))]+=f[i]*2*a[j][k]/cnt/(cnt-1);
}
}
for(int i=1;i<=n;i++)
printf("%.6lf ",f[1<<(i-1)]);
return 0;
}