luogu CF16E Fish

题目描述

有n条鱼,编号从1到n,住在湖里。每天有一对鱼相遇,

彼此相遇的概率是一样的。如果两条标号为i和j的鱼见面,第一只吃了第二只的概率为a{i,j},第二只会吃了第一只的概率为a{j,i}=1-a{i,j} 。所描述的过程继续进行,直到湖里只剩下一条鱼。请你算出每只鱼最后存活在湖里的可能性。

输入格式

第一行包含整数n( 1<=n<=18)--湖里的鱼数量。接下来n行为实数矩阵a,其中a{i,j}代表相遇时第i条鱼吃掉第j条的概率。数据保证主对角线上只包含0,且a{j,i}=1-a{i,j} 。每个实数小数点后只有6位。

输出格式

输出n个六位小数,以空格隔开,其中第i个表示第i条鱼存活到最后的概率。


状态压缩,直接模拟这个过程

#include<bits/stdc++.h>
#define db double
using namespace std;
const int N=1<<18;
int n; db dp[N],a[20][20];
int main(){
	cin>>n; for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%lf",&a[i][j]);
	int MAX=(1<<n)-1; dp[MAX]=1;
	for(int S=MAX-1;S;S--){
        int cnt=0,op=S;
		while(op){cnt+=op&1;op>>=1;}
		for(int i=1;i<=n;i++){
			if((1<<(i-1))&S)continue;
			for(int j=1;j<=n;j++){
				if(!((1<<(j-1))&S))continue;
				dp[S]+=dp[S|((1<<i-1))]*a[j][i]/(cnt*(cnt+1)/2);
			}
		}
	}
	for(int i=1;i<=n;i++)printf("%.6lf ",dp[1<<(i-1)]);
}
原文地址:https://www.cnblogs.com/naruto-mzx/p/11845820.html