Problem F CodeForces 16E
Description
n fish, numbered from 1 to n, live in a lake. Every day right one pair of fish meet, and the probability of each other pair meeting is the same. If two fish with indexes
i and j meet, the first will eat up the second with the probability aij, and the second will eat up the first with the probability a
Input
The first line contains integer n (1 ≤ n ≤ 18) — the amount of fish in the lake. Then there follow n lines with n
Output
Output n space-separated real numbers accurate to not less than 6 decimal places. Number with index i should be equal to the probability that fish with index i will survive to be the last in the lake.
Sample Input
Input2 0 0.5 0.5 0Output
0.500000 0.500000Input
5 0 1 1 1 1 0 0 0.5 0.5 0.5 0 0.5 0 0.5 0.5 0 0.5 0.5 0 0.5 0 0.5 0.5 0.5 0Output
1.000000 0.000000 0.000000 0.000000 0.000000
此題可以輕易地想到狀態壓縮動態規劃。
首先 狀態 100010010011 中 1表示fish還活著 0反之。
接下來 我們把11111111111 賦值為1,開始運算。
每次都讓一條fish被吃掉,也就是說找2條還活著的魚。
注意這裡魚從0開始計數到n-1。
第j條fish 活著 可以用 i&(1<<j)==1 判斷。
接下來再找一條k。新狀態為i^(1<<k) 。
至於概率的計算可以看程式理解一下。
程式碼如下
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int Ms=1<<20;
const int Mn=20;
double f[Ms],a[Mn][Mn];
int n,all;
int getfish(int s)
{
int fish=0;
while (s!=0)
{
fish+=s&1;
s>>=1;
}
return fish;
}
int main()
{
scanf("%d",&n);
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
scanf("%lf",&a[i][j]);
all=(1<<n)-1;
f[all]=1;
for (int i=all;i>=1;i--)
{
int fish=getfish(i);
if (fish==1) continue;
double c=2*f[i]/fish/(fish-1);
for (int j=0;j<n;j++)
if (i&(1<<j))
{
for (int k=0;k<n;k++)
if (i&(1<<k))
{
f[i^(1<<k)]+=c*a[j][k];
}
}
}
for (int i=0;i<n;i++)
printf("%.6lf ",f[1<<i]);
return 0;
}