列表

详情


NC232850. 鱼

描述

池塘中有n条鱼,编号为1n。每天有两条鱼会相遇,任意两条鱼相遇的概率相同。若编号为i的鱼与编号为j的鱼相遇,鱼i吃掉鱼j的概率为,鱼j吃掉鱼i的概率为。这个过程将一直持续,直到池塘中只剩下一条鱼。对每条鱼,求出其生存到最后的概率。

输入描述

第一行输入一个整数n (),表示鱼的个数。
接下来的n行,每行n个实数。其中第i行的第j个实数表示鱼i吃掉鱼j的概率。保证所有实数至多有6位小数,

输出描述

输出n个用空格分隔的实数,其中第i个数表示第i条鱼存活到最后的概率。与答案的绝对或相对误差不超过即为正确。

示例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 ;
}

上一题