1192:放蘋果
阿新 • • 發佈:2018-09-02
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,intn) 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:放蘋果