整数划分递归相关问题
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?算法設計----整數劃分遞歸相關問題
一.原問題
整數劃分,是指把一個正整數n寫成如下形式:
假設整數n,能被劃分為i段n=a1+a2+...ai,其中ak為n中劃分的最大整數(1<=ak<=n,1<=k<=i),則{a1,a2...ai}是n的ak的一個劃分
當n=6時我們可以獲得以下這幾種劃分
一共有11種
分析:討論整數n和劃分的最大整數m的關系,可以分為以下幾種情況:
? ? ? ?①當整數n==1,只有一種劃分,即{1}
? ? ? ?②當劃分的最大整數m==1時,只有一種劃分,即{1,1......1}
? ? ? ?③當n<m時,整數n可以劃分的最大的數為n,即f(n,n)種劃分
? ? ? ?④當n==m時,根據需不需要劃分最大整數m,可以分為兩種情況:
? ? ? ? ? ? ? a:需要劃分最大整數為m,只有一種劃分,即{m}
? ? ? ? ? ? ? b:不需要劃分最大整數為m,即可能劃分的最大整數為m-1,即有f(n,m-1)種劃分
? ? ? ?⑤當n>m時,根據需不需要劃分最大整數m,可以分為兩種情況:
? ? ? ? ? ? ? a:需要劃分最大整數為m,所以繼續在n-m中劃分,劃分的最大整數還可能為m,所以有f(n-m,m)種劃分
? ? ? ? ? ? ? b:不需要劃分最大整數為m,所以劃分的最大整數可能為m-1,即有f(n,m-1)種劃分
? ? ? ?綜上所述的轉移狀態方程:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1? ? ? ? ? ? ? ? ? 當?n==1或 m==1時
? ? ? ? ? ? ? f(n,m)=? ? ?f(n,n)? ? ? ? ? ?當n<m時
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1+f(n,m-1)? ?當n==m時
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?f(n-m,m)+f(n,m-1)? ?當n>m時
python源代碼:
? #整數劃分問題 #假設整數n,能被劃分為i段n=a1+a2+...ai,其中ak為n中劃分的最大整數(ak<=n,k<=i),其中{a1,a2...ai}是n的ak的一次劃分 #現在求整數n能夠劃分成多少種 def huafen(n,m): #n為整數,m為劃分的最大整數,m<=nif(n==1 or m==1):return 1elif n==m:return 1+huafen(n,m-1) elif(n<m):return huafen(n,n)else:return huafen(n,m-1)+huafen(n-m,m)a=[] t=0 def digui(sum,k,m,l):global aglobal tif(sum>l):returnelif(sum==l):t+=1print("第",t,"種:")for x in range(len(a)-1):print(str(a[x])+"+",end="")print(a[-1])else:c=range(m)for y in reversed(c):y+=1sum+=y a.append(y) #加入到a列表中digui(sum,k+1,y,l) #遞歸調用a.pop() #出列表,恢復現場,回溯sum-=y #恢復現場,回溯def main():print("請輸入一個整數:")v=int(input())p=huafen(v,v)print("該整數的劃分一共有"+str(p)+"種")print("所有的劃分如下:")digui(0,0,v,v)main()?運行結果如下:
二.變形1
如果限制每一個劃分的整數不能一樣,即劃分的每一個整數不同? ,則又有多少種劃分呢?
其實我們只需在原問題進行修改即可:
①當m==1時,我們需要設置{1,1,1,....1}為0種
②當n>m時,我們需要修改的是當需要選取最大整數m時? ,我們將最大值m-1,即f(n-m,m-1)?種
其余的不需要修改? ?
pythoon源碼:
#整數劃分變形問題 def huafen(n,m): #n為整數,m為劃分的最大整數,m<=nif(n==1):return 1elif(m==1): #當m==1時,設置1,1,1.....1}為0種return 0elif n==m:return 1+huafen(n,m-1)elif(n<m):return huafen(n,n)else:return huafen(n,m-1)+huafen(n-m,m-1) #使下次劃分的整數小于上次的劃分的最大整數a=[] t=0 def digui(sum,k,m,l):global aglobal tif(sum>l):returnelif(sum==l):t+=1print("第",t,"種:")for x in range(len(a)-1):print(str(a[x])+"+",end="")print(a[-1])else:c=range(m)for y in reversed(c):y+=1sum+=ya.append(y)digui(sum,k+1,y-1,l) #這里需要將下一次的最大劃分整數修改為上一次劃分最大整數-1,不能與上一次相同a.pop()sum-=ydef main():print("請輸入一個整數:")v=int(input())p=huafen(v,v)print("該整數的劃分一共有"+str(p)+"種")print("所有的劃分如下:")digui(0,0,v,v) main()運行結果如下:
三.變形2
如果限制每次劃分的整數的個數?,則又有多少種劃分呢?(類似與盤子分蘋果問題)
(其中n為整數,每次劃分只能劃分為m個數)
分析:①當m==1時,只有一種劃分,即{n}
? ? ? ? ? ?②當n<m時,由于劃分的整數不可能為負數和小數,則劃分不盡,所以為0
? ? ? ? ? ?③當n==m時,也是只有一種劃分。即{1,1,1,1...1}
? ? ? ? ? ?④當n>m時,根據劃分的整數中是否包含1,可以分為兩種情況:
? ? ? ? ? ? ? ? ?a:劃分的整數中至少有一個1,則在n-1中繼續劃分為m-1份,即f(n-1,m-1)種劃分
? ? ? ? ? ? ? ? ?b:劃分的整數中沒有1,所以m個部分劃分的整數必須都大于1,所以先給m個部分設為1,接著將剩余的n-m整數對m個部分分別加數,即要保證m個部分均大于1,即n-m>=m,則總共有f(n-m,m)種;如果n-m<m,則f(n-m,m)為0,所以條件②不能省略
? ? ? ? ? 綜上所述方程:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1? ? 當m==1 或者 n==m 時
? ? ? ? ? ? ?f( n,m) =? ? 0? ?當m>n時
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? f(n-1,m-1)+f(n-m,m)? ? 當n>m時
python源代碼:
#整數劃分變形問題 def huafen(n,m): #n為整數,m為每次劃分的整數個數if(m==1 or n==m):return 1elif(m>n): #當m>n時return 0else:return huafen(n-1,m-1)+huafen(n-m,m) #選取至少有一個1和不選取1的種數 a=[] t=0 def digui(sum,k,m,l,q):global aglobal tif(sum>l):returnelif(k==q and sum==l):t+=1print("第",t,"種:")for x in range(len(a)-1):print(str(a[x])+"+",end="")print(a[-1])else:c=range(m)for y in reversed(c):y+=1sum+=ya.append(y)digui(sum,k+1,y,l,q) a.pop()sum-=ydef main():v,g=map(int,input("請輸入兩個以空格隔開的數:").split()) #整數v,和每次劃分的整數個數gp=huafen(v,g) print("該整數的劃分一共有"+str(p)+"種")print("所有的劃分如下:")digui(0,0,v,v,g) main()?運行結果如下:
?三.變形3? ?
? 如果n劃分成若干個奇正整數之和?,則這樣有多少種劃分?
?? ? ? (f(n,m)代表有多少種劃分,其中n為整數,m為不大于n的最大整數的劃分)
分析:①當m==1時,只有一種劃分,即{1,1,...1}
? ? ? ? ? ?②當m為奇數時:根據m和n的關系可以分成三種情況
? ? ? ? ? ? ? ? ? ? a.當n<m時,則有f(n,n)種劃分
? ? ? ? ? ? ? ? ? ? b.當n==m時,根據是否選取最大整數m,可以分成兩種情況
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*選取最大奇整數m,則只有一種劃分,即{m}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *不選取最大奇整數m,則共有f(n,m-2)種劃分
? ? ? ? ? ? ? ? ? ? ?c.當n>m時,根據是否選取最大整數m,可以分成兩種情況
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *選取最大奇整數m,則共有f(n-m,m)種劃分
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *不選取最大奇整數m,則共有f(n,m-2)種劃分
? ? ? ? ? ?③當m為偶數時:根據m和n的關系可以分成三種情況:
? ? ? ? ? ? ? ? ? ? a.當n<m時,可以分成兩類:(m為偶數,則m-1為最大奇數)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *當n<m-1時,則共有f(n,n)種劃分
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *當n==m-1時,則共有f(n,m-1)種劃分
? ? ? ? ? ? ? ? ? ? b.當n==m時,則共有f(n,m-1)種劃分
? ? ? ? ? ? ? ? ? ? ?c.當n>m時,根據是否選取最大奇整數m-1,可以分成兩種情況
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *選取最大奇整數m-1,則共有f(n-m+1,m-1)種劃分
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *不選取最大奇整數m-1,則共有f(n,m-3)種劃分
python源代碼:
def huafen(n,m): #n為整數,huafen(n,m)代表:m為劃分的最大整數共有多少種,m<=nif(m==1): #若m==1return 1elif (m%2): #若m為奇數if(n<m): #n<mreturn huafen(n,n)elif(n==m): #是否選取最大奇整數mreturn 1+huafen(n,m-2)else: #是否選取最大奇整數mreturn huafen(n-m,m)+huafen(n,m-2)else: #若m為偶數if(n<m):if(n<m-1):return huafen(n,n)else:return huafen(n,m-1)elif(n==m):return huafen(n,m-1)else: #是否選取最大奇整數m-1return huafen(n-m+1,m-1)+huafen(n,m-3) a=[] t=0 def digui(sum,k,m,l):global aglobal tif(sum>l):returnelif(sum==l):flg=1for x in a: #在原問題答案的基礎下,挑選出整數全部都是偶數的列表if(x%2==0):flg=-1breakif(flg==1):t+=1print("第",t,"種:")for x in range(len(a)-1):print(str(a[x])+"+",end="")print(a[-1])else:c=range(m)for y in reversed(c):y+=1sum+=ya.append(y)digui(sum,k+1,y,l)a.pop()sum-=ydef main():print("請輸入一個整數:")v=int(input())p=huafen(v,v)print("該整數的劃分一共有"+str(p)+"種")print("所有的劃分如下:")digui(0,0,v,v) main()運行結果如下:
? ? ? ? ?
?
? ? ? ? ?
?
?
總結
以上是生活随笔為你收集整理的整数划分递归相关问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: fraction函数的分数处理
- 下一篇: 抽象工厂模式的详解