計蒜客 A1596.蒜頭君王國 機率計算(dp)

題目描述

原題連接html

有一天,蒜頭君當上了國王。蒜頭君的王國有 n n n 坐城市,如今他須要在城市之間修建道路使得城市之間相互聯通。
蒜頭君是一個不會規劃的人,他不知道哪些城市之間必需要有道路,因此對於任意兩座城市之間,蒜頭軍會修建道路的機率爲 p p p
請你計算一下最後修建出來的道路使得 n n n 座城市都聯通的機率。ios

輸入格式

輸入包含一個整數 n ( 1 ≤ n ≤ 20 ) n(1≤n≤20) n(1n20) 和一個實數 p ( 0 ≤ p ≤ 1 ) p(0≤p≤1) p(0p1).web

輸出格式

輸出一行一個實數表示答案,輸出結果偏差在 1 0 − 5 10^{−5} 105 之內都認爲正確。svg

輸入樣例

3 0.6

輸出樣例

0.6480000

分析

參考大佬的題解
題目讓求 n n n個點都聯通的機率 F ( n ) F(n) F(n)。不妨先求一下 n n n個點組成的圖不連通的機率 G ( n ) G(n) G(n)
考慮n個點組成的圖不連通有如下 n − 1 n-1 n1中狀況:
1 1 1個點連通, 且這 1 1 1個點組成的連通塊, 與其他 n − 1 n-1 n1個點沒有邊相連
2 2 2個點連通, 且這 2 2 2個點組成的連通塊, 與其他 n − 2 n-2 n2個點沒有邊相連

k k k個點連通, 且這 k k k個點組成的連通塊, 與其他 n − k n-k nk個點沒有邊相連

n − 1 n-1 n1個點連通, 且這 n − 1 n-1 n1個點組成的連通塊, 與剩餘的 1 1 1個點沒有邊相連


考慮有 k k k個點連通的狀況:
首先要選 k k k個點, 而第 n n n個點必定選,則再從 n − 1 n-1 n1個點中選擇 k − 1 k-1 k1個, 即 C n − 1 k − 1 C_{n-1}^{k-1} Cn1k1
而後保證這 k k k個點連通, 即 F ( k ) F(k) F(k)
最後保證這 k k k的點與其他 n − k n-k nk個點沒有邊相連, 即 ( 1 − p ) k ( n − k ) (1-p)^{k(n-k)} (1p)k(nk) ( p p p爲兩點間修路的機率)
從而根據上述 n − 1 n-1 n1種狀況求出 G ( n ) G(n) G(n), 則 題目所求 F ( n ) = 1 − G ( n ) F(n) = 1-G(n) F(n)=1G(n)spa

實現

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const int N = 29;
int n;
double p;
double f[N]; // f[i]表示n個點都聯通的機率
int c(int a, int b) // 計算組合數 C(a,b), 即從a個點中選b個點
{
    int sum = 1;
    for(int i=1; i<=b; i++) sum = sum*(a-b+i)/i;
    return sum;
}
int main()
{
    cin >> n >> p;
    f[1] = 1, f[2] = p; // 易知: 1個點聯通的機率爲1, 2個點聯通機率爲p;
    for(int i=3; i<=n; i++)
    {
        double fail = 0; // 表示i個點不聯通的機率
        for(int j=1; j<=i-1; j++)
        {
            fail += ( c(i-1, j-1)*f[j]*pow(1.0-p,j*(i-j)) );
        }
        f[i] = 1.0-fail;
    }
    printf("%.7lf",f[n]);
    return 0;
}

關於上述實現中組合數 C n m C_n^m Cnm的計算

在這裏插入圖片描述

相關文章
相關標籤/搜索