Codeforces 16E Fish 题解

题意简述

个鱼,其中第个鱼把第个与吃掉的概率是,保证。会有轮,每一轮会等概率随机选择两个鱼来比♂拼,然后直到最后只剩下一个鱼。对于每个鱼,求最后剩下它的概率。

顺便膜鱼,鱼tql%%%

思路框架

状压。对于每个状态,枚举已有的鱼,枚举上一次被吃掉的鱼,加一下。

具体思路

表示剩下活着的鱼状态为的概率。那么,我们在中找到一条鱼,设它为上一次获胜的。那么上一次死掉的肯定不在里面了,就到外面去找一条上一次死掉的鱼。设中包含条鱼,那么。其中表示中加入,用位运算表示为 是选择 出来比♂拼的概率,吃掉的概率。

然后转移一下。答案就是只选i的状态。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 18
#define real double
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)

int n;
real a[N][N];
void Input()
{
scanf("%d",&n);
F(i,0,n-1) F(j,0,n-1) scanf("%lf",&a[i][j]);
}

real dp[1<<N];
void Soviet()
{
int All=(1<<n)-1;
dp[All]=1.00;
D(i,All-1,0)
{
real cnt=(real)__builtin_popcount(i);
F(j,0,n-1) if (!((1<<j)&i))
{
F(k,0,n-1) if ((1<<k)&i)
{
real P=1/(cnt*(cnt+1)/2.00);
dp[i]+=dp[i|(1<<j)]*a[k][j]*P;
}
}
}
F(i,0,n-1)
{
printf("%.6f ",dp[(1<<i)]);
}putchar('\n');
}

#define Flan void
Flan IsMyWife()
{
Input();
Soviet();
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}

最后问一下,那个标题为什么显示不出来啊,有没有人救救我。。。

w