1. 程式人生 > >1192:放蘋果

1192:放蘋果

script () 配方 blank 統計 out blog 以及 min

題目連接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1192

一遞歸方式:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int m,n;
 4 int up(int m,int n)
 5 {
 6     if(m==0||n==1)return 1;
 7     if(m<n)return up(m,m);
 8     else return up(m,n-1)+up(m-n,n);
 9 }
10 int main()
11 {
12     int s;
13     cin>>s;
14 while(s--) 15 { 16 cin>>m>>n; 17 cout<<up(m,n)<<endl; 18 } 19 return 0; 20 }

二遞推(簡單動態規劃),從某種意義講遞推和動歸很難區分

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int a[20][20];//狀態:a[m][n]表示m個蘋果放在n個盤子裏的方法數
 5 int f(int m,int
n) 6 { 7 int i,j; 8 for(i=1;i<=n;i++)//0個蘋果 9 a[0][i]=1; 10 for(i=1;i<=m;i++)//1個盤子 11 a[i][1]=1; 12 for(i=1;i<=m;i++) 13 for(j=2;j<=n;j++) 14 if(i<j) 15 a[i][j]=a[i][i]; 16 else 17 a[i][j]=a[i][j-1
]+a[i-j][j]; //狀態轉移方程 18 } 19 int main() 20 { 21 int m,n,i,j,k; 22 cin>>k; 23 for(i=1;i<=k;i++) 24 { 25 cin>>m>>n; 26 f(m,n); 27 cout<<a[m][n]<<endl; 28 } 29 return 0; 30 }

三、其他博客方法總結(摘自https://blog.csdn.net/QiaoRuoZhuo/article/details/80583072)

  1 /*
  2     Name: 放蘋果問題集錦(每個盤子至少放1個蘋果) 
  3     Copyright: 
  4     Author: 
  5     Date: 31-07-17 21:22
  6     Description: 放蘋果
  7 查看 提交 統計 提問
  8 總時間限制: 1000ms 內存限制: 65536kB
  9 描述
 10 把N個同樣的蘋果放在M個同樣的盤子裏,允許有的盤子空著不放,問共有多少種不同的分法?(用K表示)5,1,1和1,5,1 是同一種分法。
 11 輸入
 12 第一行是測試數據的數目t(0 <= t <= 20)。以下每行均包含二個整數M和N,以空格分開。1<=M,N<=10。
 13 輸出
 14 對輸入的每組數據N和M,用一行輸出相應的K。
 15 樣例輸入
 16 1
 17 7 3
 18 樣例輸出
 19 4
 20 算法思路:
 21 回溯算法:有2種思路,一種是確保後面的盤子中蘋果不比前面的少,另一種是確保後面的盤子中蘋果不比前面的多。  
 22 第2種思路遞歸深度較少,但代碼復雜些,特別要註意第n個盤子能放蘋果的數量範圍。   
 23 基本上遞歸問題都可以轉化為記憶化搜索,然後轉換為動態規劃問題。 
 24 回溯算法相當於窮舉,不但可以獲得組合的數量,還可以存儲具體的解空間。
 25 記憶化搜索和動態規劃算法均采用了確保後面的盤子中蘋果不比前面的多的思路;其中動態規劃進行了降維優化。 
 26 每個盤子至少放1個蘋果和每個盤子至少放0個蘋果的遞歸表達式以及邊界條件都不一樣。 
 27 */
 28 #include<iostream>
 29  
 30 using namespace std;
 31                
 32 const int MAXN = 10; //蘋果的最大數量 
 33 const int MAXM = 10; //盤子的最大個數
 34 int A1[MAXN+1], A2[MAXN+1]; 
 35 int M, N, s1, s2; 
 36 long long B[MAXM+1][MAXN+1]; //記錄給定n個盤子裝m個蘋果的方案總數 
 37 long long B2[MAXM+1][MAXN+1]; //記錄給定n個盤子裝m個蘋果的方案總數 
 38 long long pre[MAXN+1]; //記錄給定n個盤子裝m個蘋果的方案總數 
 39 long long cur[MAXN+1]; //記錄給定n個盤子裝m個蘋果的方案總數 
 40 long long F[MAXN+1]; //記錄給定n個盤子裝m個蘋果的方案總數 
 41  
 42 void DFS_1(int k, int n); //n表示共n個蘋果,k表示第k個盤子   
 43 void DFS_2(int k, int n); //n表示共n個蘋果,k表示第k個盤子
 44 long long Fun(int k, int n); //記憶化搜索
 45 void Fun2(int k, int n); //動態規劃:使用二維數組 
 46 long long Fun3(int k, int n); //動態規劃:使用2個一維數組 
 47 long long Fun4(int k, int n); //動態規劃:使用1個一維數組 
 48  
 49 int main() 
 50 {
 51     int t;
 52      
 53     Fun2(MAXM, MAXN); 
 54     cin >> t;      
 55     for (int k=0; k<t; k++)      
 56     {      
 57         cin >> N >> M;      
 58              
 59         s1 = 0;     
 60         DFS_1(1, N);      
 61         cout << s1 << endl;    
 62         
 63         s2 = 0;     
 64         int minNum = N/M + (N%M!=0);     
 65         for (A2[1]=N-M+1; A2[1]>=minNum; A2[1]--)//第一個盤中放A2[1]個蘋果     
 66         {      
 67             DFS_2(2, N-A2[1]);      
 68         }    
 69         cout << s2 << endl; 
 70         
 71         cout << Fun(M, N) << endl; 
 72         cout << B2[M][N] << endl; 
 73         cout << Fun3(M, N) << endl; 
 74     }      
 75     
 76     return 0;
 77 }
 78  
 79 void DFS_1(int k, int n) //n表示共n個蘋果,k表示第k個盤子       
 80 {      
 81     if (k == M)//最後一個盤子      
 82     {      
 83         A1[k] = n;      
 84         cout << s1 << " : ";      
 85         for (int i=1; i<=k; i++)      
 86             cout << A1[i] << " ";      
 87         cout << endl;      
 88         s1++;      
 89     }      
 90     else  //至少還有2個盤子    
 91     {      
 92         for (A1[k]=max(1,A1[k-1]); A1[k]+A1[k]<=n; A1[k]++)      
 93         {   //確保剩下的蘋果不比當前盤子中的少       
 94             DFS_1(k+1, n-A1[k]);   
 95         }      
 96     }         
 97 }     
 98  
 99 void DFS_2(int k, int n) //n表示共n個蘋果,k表示第k個盤子   
100 {      
101     if (n <= 0)
102         return;
103         
104     if (k == M)//最後一個盤子 
105     {     
106         if (n > A2[k-1]) //確保後面的盤子中蘋果不比前面的多  
107             return;
108         A2[k] = n;    
109         cout << s2 << " : ";      
110         for (int i=1; i<=k; i++)     
111             cout << A2[i] << " ";  
112         cout << endl;      
113         s2++;      
114     }      
115     else      
116     {   
117         int maxNum = min(n, A2[k-1]);//確保後面的盤子中蘋果不比前面的多 
118         for (A2[k]=maxNum; A2[k]>=1; A2[k]--)       
119         {           
120             DFS_2(k+1, n-A2[k]);       
121         }      
122     }         
123 } 
124  
125 long long Fun(int k, int n) //記憶化搜索
126 {   
127     if (B[k][n] != 0)
128         return B[k][n]; 
129     if (k == 1 || n == k)//只有1個盤子或者盤子與蘋果數量相等 
130         B[k][n] = 1;
131     else if (n < k) //蘋果數量少於盤子 
132         B[k][n] = 0;
133     else //兩種情況:第k個盤子只放一個蘋果;每個盤子至少放2個蘋果,則每個盤子中拿走1個蘋果後,分配方法數量不變 
134         B[k][n] = Fun(k-1, n-1) + Fun(k, n-k);
135     
136     return B[k][n];
137 }  
138  
139 void Fun2(int k, int n) //動態規劃:使用二維數組 
140 {   
141     for (int j=1; j<=n; j++)//j個蘋果放到1個盤子裏 
142         B2[1][j] = 1; 
143     for (int i=2; i<=k; i++) 
144     {  
145         for (int j=i; j<=n; j++) 
146         {  
147             B2[i][j] = B2[i-1][j-1] + B2[i][j-i];  
148         }  
149     }  
150 }  
151  
152 long long Fun3(int k, int n) //動態規劃:使用2個一維數組 
153 {   
154     for (int j=1; j<=n; j++)//j個蘋果放到1個盤子裏 
155         pre[j] = 1; 
156     for (int i=2; i<=k; i++) 
157     {  
158         for (int j=1; j<i; j++) //蘋果數量少於盤子 
159         {  
160             cur[j] = 0;  
161         }  
162         for (int j=i; j<=n; j++) 
163         {  
164             cur[j] = pre[j-1] + cur[j-i];  
165         }  
166         for (int j=1; j<=n; j++) 
167         {  
168             pre[j] = cur[j];  
169         }  
170     }  
171     
172     return pre[n];
173 }    

1192:放蘋果