概述
题目链接:点击打开链接
题意:池中有n条鱼,每天会有两条鱼相遇,任意两条鱼两两相遇的概率相等,如果两条鱼相遇,其中一条一定会被吃掉,给出所有两两相遇时吃与被吃的概率,求每条鱼存活的概率。
状态转移方程: dp[s2]=∑(win[j][i]*dp[s]/C[num][2]);
i∈s
s2=s^i;
j∈s2,
起点 : dp[1<<n]=1
因为没有被吃的固定顺序,所以应该用集合表示状态。
考虑到存活的鱼两两相遇的概率相等,要用组合公式。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define ysk(x) (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn=18 ;
int ed,n;
double win[maxn+10][maxn+10];
double dp[262144+10];
int C[maxn+5][maxn+5];
void pre()
{
C[0][0]=1;
for(int i=1;i<=maxn;i++)
{
C[i][0]=C[i][i]=1;
for(int j=1;j<i; j++)
{
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
}
int getfishnum(int s)//统计存活的鱼的数量
{
int ans=0;
for0(i,n) if(s&ysk(i))
{
ans++;
}
return ans;
}
int main()
{
pre();
while(~scanf("%d",&n))
{
for0(i,n) for0(j,n) scanf("%lf",&win[i][j]);
ed=ysk(n)-1;
memset(dp,0,(ed+1)*sizeof dp[0]);
dp[ed]=1;
for(int s=ed;s>=0;s--)
{
int num=getfishnum(s);
for0(i,n) if(ysk(i)&s)//枚举第一个被吃的鱼
{
int s2=s^ysk(i);
for0(j,n) if(s2&ysk(j))//枚举吃它的鱼
{
dp[s2]+=win[j][i]*dp[s]/C[num][2];//因为任意两条鱼两两相遇的概率相等
}
}
}
for0(i,n)
{
if(i) putchar(' ');
printf("%f",dp[ysk(i)]);
}
putchar('n');
}
return 0;
}
最后
以上就是傲娇马里奥为你收集整理的Codeforces 16E Fish dp(概率)的全部内容,希望文章能够帮你解决Codeforces 16E Fish dp(概率)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复