計算烷烴的同分異構體個數 (結構異構)


  本質上就是一個無標號無根樹帶度數限制的計數問題.

將問題一般化:

  求 n 個點的無標號無根樹的個數, 且每個點的度數不超過 m.

烷基 (有根樹)

  首先考慮計算烷基的個數 (即有根樹).

  考慮暴力 DP. 設狀態為 $f(i,j,k)$, 表示當前共有 $i$個點, 最大的子樹大小為 $j$, 且根的度數為 $k$. 對於狀態 $f(i,j,k)$, 通過枚舉最大子樹的個數 l 和次大子樹的大小 size, 有

$f(i,j,k)=∑_{l}∑_{s}+f(i−jl,size,k−l)\left\{ \begin{matrix}s+l-1\\l \end{matrix}  \right\}$


  其中 $s=∑^{j}_{a=1}∑^{m−1}_{b=0}f(j,a,b)$, 組合數是用來可重集計數的.

  這是$ O(n^3m^2) $的. 顯然可以前綴和優化, 但是空間撐不住. 還可以做得更好.

  考慮如何省掉 $j$ 這一維狀態. 即設狀態為 $f(i,j)$, 表示當前共有 $i$ 個點, 根的度數為 $k$.

  考慮 DP 的一個技巧: 強行規定轉移順序. 即, 先 $1. . .n$ 枚舉 size, 表示強制用最大子樹大小為 size 的情形來轉移. 不妨設

  $ s=∑^{m−1}_{k=0}f(size,k)$,

  那么對於一個 $f(i,j)$, 再枚舉一個最大子樹 (即子樹大小為 size 的子樹) 的個數 k, 我們便有轉移

$f(i,j)←f(i,j)+f(i−size×k,j−k)\left\{ \begin{matrix}s+k-1\\k \end{matrix}  \right\}$


  這是 $O(n^2m^2)$ 的. 如果是算烷基的話, 便是 $O(n^2)$ 的.

烷烴 (無根樹)

  本來我想枚舉主鏈長度來做的, 后來發現直接利用樹的重心來做非常方便.

  首先只要某個點 $u$ 滿足其子樹大小都 $≤n2$, 那么這個點是這顆樹的重心. 比較顯然的是, 重心最多只會有兩個, 並且有兩個重心的情形, 兩個重心一定相鄰, 並且另一個重心做根的時候, 這個重心的子樹大小為 $n2$. (當然 $n$ 必須要是偶數)

  然后很多無根樹同構的問題就可以通過重心轉化為有根樹同構. 烷烴就可以這么計數. 因為我們可以在 DP 烷基的時候, 強制$ size<n2 $(注意是小於), 這樣求出的 $f(i,j)$ 就是點數為 $i$ 且重心度數為 $j$ 的無根樹個數. 那么答案為:

$\sum^m_{k=0}f(n,k)+[n\pmod{2}=0]  \left\{ \begin{matrix}\sum^{m−1}_{k=0}f(\frac{n}{2},k)+1\\2 \end{matrix}  \right\} $


前一項為一個重心的情形, 后一項為兩個重心的情形.

代碼附上

 

def C(n, k):
    ret = 1
    for i in range(k):
    ret *= n - i
    for i in range(1, k + 1):
    ret //= i
    return ret

def calc(n, m):
    dp = [[0 for i in range(m + 1)] for i in range(n + 1)]
    dp[1][0] = 1
    for size in range(1, (n - 1) // 2 + 1):
    s = sum(dp[size][:-1])
    for i in range(n, size, -1):
        for j in range(1, m + 1):
        for k in range(1, j + 1):
            if size * k < i:
            dp[i][j] += dp[i - size * k][j - k] * C(s + k - 1, k)
    ret = sum(dp[n])
    if n % 2 == 0:
    ret += C(sum(dp[n // 2][:-1]) + 1, 2)
    return ret

n = int(input())
print(calc(n, 4))

 

出處:
計算烷烴的同分異構體個數(結構異構) 【J.O】_Debug

鏈接:http://debug18.com/posts/calculate-the-number-of-structural-isomers-for-alkanes/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM