OpenJudge簡單的整數劃分問題兩種方法(DFS)(動態規劃0ms),全域性題號7215,已AC
阿新 • • 發佈:2019-02-10
2:簡單的整數劃分問題
- 總時間限制:
- 100ms
- 記憶體限制:
- 65536kB
- 描述
-
將正整數n 表示成一系列正整數之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。
正整數n 的這種表示稱為正整數n 的劃分。正整數n 的不同的劃分個數稱為正整數n 的劃分數。 - 輸入
- 標準的輸入包含若干組測試資料。每組測試資料是一個整數N(0 < N <= 50)。
- 輸出
- 對於每組測試資料,輸出N的劃分數。
- 樣例輸入
-
5
- 樣例輸出
-
7
- 提示
- 5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1
- 方法一:採用DFS的方法,對目標進行深度搜索,如圖所示
- 上面只畫了一部分的結點,就類似於一個結點一個結點的往下搜尋,搜尋到符合結果的就cnt++.
- 一般能畫出這種樹狀圖的都能用DFS。DFS的核心程式碼在我的ZOJ1002文章裡有提到。
- 方法二:
- 例如數字5(以j表示),有1 2 3 4 5五個因子(下面以i代表第五個) ,每一個因子在選擇時都有選與不選兩種選擇。
- 例如如果選5
- 問題就變成 0 ,1 2 3 4 5。這就直接return了
- 如果不選5
- 問題就變成5, 1 2 3 4。
- 以此類推,後面的步驟和前面都是一樣的。所以我們可以把問題分解為兩種情況
- (j,i) + (j-i,i) //j 代表還有多少能減 , i代表還有前i個數
- 方法一:
#include <iostream> using namespace std; int cnt=0;//記錄方案次數 int n;//輸入的數值 void dfs(int sum,int k)//sum為每次嘗試的和,k為下一結點的值 { if(sum>=n)//如果大於n就需判斷是否符合 { if(sum==n) cnt++; } if(k<1)return;//1後面就沒了 for(int i=k;i>0;i--)//每個結點都有1~k個分支 { if(sum<n)//小於n才有新的分支 { sum=sum+i; if(sum>=n)//例如3+2=5的情況 { dfs(sum,i-1);//進入下一個結點 } else dfs(sum,i);//例如1+1+1+1+1=5的情況,進入下一個結點 sum=sum-i;//復原,因為一個結點會有多個分支。 } } } int main() { while(cin>>n) { dfs(0,n); cout<<cnt<<endl; cnt=0; } return 0; }
方法二:#include <iostream> #include <cstring> using namespace std; int way(int i,int j); int ways[55][55]; int main() { int n; while(cin>>n) { memset(ways,0xff,sizeof(ways));//全部賦值為-1 cout<<way(n,n)<<endl; } return 0; } int way(int i,int j) { int result=0; if(j==0) return 1; if(i==0) return 0; if(ways[i][j]!=-1)//如果這種情況已經做過直接返回 return ways[i][j]; if(j>=i) result+=way(i,j-i); result+=way(i-1,j); ways[i][j]=result;//狀態記錄 return result; }