【Python3】【樹形dp】uva10253 Series-Parallel Networks

設「共n個葉子,且每一個非葉節點至少有兩個子節點」的樹的數量爲f[n],再乘2就是本題答案。python

設狀態d(i,j)表示每棵子樹最多包含i個葉子、一共有j個葉子的樹的個數。因而f(n)=d(n-1,n)。假設剛好包含i個葉子的子樹有p棵,那麼這些樹的組合數等於從f(i)棵樹中選擇p棵樹的方案數,即C(f(i)+p-1,p),再去乘上剩下的(包含葉子樹少於i的)子樹的方案數d(i-1,j-p*i),所以d(i,j)=sum{C(f(i)+p-1,p)*d(i-1,j-p*i) | p>=0,p*i<=j}blog

邊界是:i>=0時d(i,0) = 1,i>=1時d(i,1) = 1,但d(0,i) = 0。input

def C(n, m):
    res = 1;
    for i in range(m):
        res *= (n-i);
    for i in range(1,m+1):
        res //= i;
    return res;

f = [0] + [1] + [0] * 33;
d = [([0] * 35) for i in range(35)];
n = 30;
for i in range(n+1):
    d[i][0]=1;
for i in range(1,n+1):
    d[i][1]=1;
    d[0][i]=0;
for i in range(1,n+1):
    for j in range(2,n+1):
        for p in range(0,j+1,i):
            d[i][j] += C(f[i]+p//i-1, p//i) * d[i-1][j-p];
    f[i+1] = d[i][i+1];
while(True):
    n=int(input());
    if(n==0):
        break;
    if(n==1):
        print(1);
    else:
        print(2*f[n]);
相關文章
相關標籤/搜索