NC232850. 鱼
描述
输入描述
第一行输入一个整数 (),表示鱼的个数。
接下来的行,每行个实数。其中第行的第个实数表示鱼吃掉鱼的概率。保证所有实数至多有6位小数,,。
输出描述
输出个用空格分隔的实数,其中第个数表示第条鱼存活到最后的概率。与答案的绝对或相对误差不超过即为正确。
示例1
输入:
2 0 0.5 0.5 0
输出:
0.500000 0.500000
示例2
输入:
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 0
输出:
1.000000 0.000000 0.000000 0.000000 0.000000
C++(g++ 7.5.0) 解法, 执行用时: 66ms, 内存消耗: 3304K, 提交时间: 2023-04-20 17:56:30
#include <vector> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; #define endl '\n' using LL=long long; using LD=long double; constexpr int N=18; LD a[N][N],dp[1<<N]; vector<int> st[N]; void solve() { int n; cin>>n; for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin>>a[i][j]; for(int i=0;i<1<<n;i++) st[__builtin_popcount(i)].push_back(i); dp[0]=1; for(int i=0;i<n-1;i++) { int left=n-i; const LD p=LD(2)/(left*(left-1)); for(int j:st[i]) { for(int x=0;x<n;x++) { if(j&1<<x) continue; for(int y=x+1;y<n;y++) { if(j&1<<y) continue; dp[j|1<<x]+=p*a[y][x]*dp[j]; dp[j|1<<y]+=p*a[x][y]*dp[j]; } } } } cout<<fixed<<setprecision(6); for(int i=0;i<n;i++) cout<<dp[((1<<n)-1)^(1<<i)]<<' '; } int main() { ios::sync_with_stdio(0); cin.tie(nullptr); solve(); return 0; }
C++ 解法, 执行用时: 50ms, 内存消耗: 1400K, 提交时间: 2022-02-09 10:19:33
#include<bits/stdc++.h> #define N 19 #define LL long long using namespace std ; int n ; double f[2000000],a[25][25] ; int main() { scanf("%d",&n) ; for(int i=1;i<=n;++i) for(int j=1;j<=n;j++) scanf("%lf",&a[i][j]) ; int t=(1<<n)-1 ; f[t]=1.0 ; for(int i=t-1;i>=1;--i) { for(int j=1;j<=n;j++) if(!(i&(1<<(j-1)))) { for(int k=1;k<=n;++k) if(i&(1<<(k-1))) f[i]+=f[i|(1<<(j-1))]*a[k][j] ; } } double res=0 ; for(int i=0;i<n;++i) res+=f[1<<i] ; for(int i=1;i<=n;++i) printf("%.7lf ",f[1<<(i-1)]/res) ; return 0 ; }