放苹果 POJ - 1664
https://vjudge.net/problem/POJ-1664
题意:
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?
DFS
思路
用的深搜的办法,每次后面的数都会 大于等于 前面的数字。
代码:
int n, m, sum;
void dfs(int x, int step, int y)
{
if (step > m || x > n)
return;
else if (x == n && step == m)
{
sum++;
return;
}
for (int i = y; i <= n; i++)
dfs(i + x, step + 1, i);
}
void solve()
{
int t;
cin >> t;
while (t--)
{
sum = 0;
cin >> n >> m;
dfs(0, 0, 0);
cout << sum << endl;
}
}
DP
原文
思路
设f[m][n]表示把m个苹果放到n个盘子里的不同方法的种数。
-
当盘子数n为1的时候,只有一种放法,就是把所有苹果放到一个盘子里。
-
当苹果数m为1的时候,也只有一种放法,因为盘子之间并无顺序,所以不管这个苹果放在哪个盘子里,结果都算一个。
-
当m<n时,m个苹果最多只能放到m个盘子中去(一个盘子里放一个),盘子有多余的。此时,实际上就相当于把m个苹果放到m个盘子里一样,也就是f[m][m]。
-
当m>=n时,可分两种情况讨论。
-
- 一种是至少有一个盘子里不放苹果,这就相当于f[m][n-1];
-
- 另一种是先取出n个苹果一个盘子里放一个,再将剩下的m-n个苹果放到n个盘子里去,即f[m-n][n]。
代码:
int n, m;
int dp[N][N];
void solve()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> m;
dp[0][0] = 1;
for (int i = 1; i <= m; i++)
{
for (int j = 0; j <= n; j++)
{
if (j - i >= 0)
dp[i][j] = dp[i - 1][j] + dp[i][j - i];
else
dp[i][j] = dp[i - 1][j];
}
}
printf("%d\n", dp[m][n]);
}
}
母函数模板题(待学)
母函数文章
思路
代码:
//母函数模板题:M个相同球放到N个相同的盒子中 G(x) = (1+x+x^2+x^3+...x^k+...)*(1+x+x^2+x^3+...x^k+...)*...(一共有 n 项)我们要求的就是x^m前面的系数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<cmath>
using namespace std;
int n;
struct Z{
int val;
int num;
}z[10000];
int ans[100005],ans0[100005];
int main(){
int t;
cin>>t;
while(t--){
int m,n;
cin>>m>>n;
for(int i=0;i<=m;i++){
ans[i]=1;
ans0[i]=0;
}
for(int i=2;i<=n;i++){
for(int j=0;j<=m;j++){
for(int k=0;j+k<=m;k+=i)
ans0[j+k]+=ans[j];
}
for(int j=0;j<=m;j++){
ans[j]=ans0[j];
ans0[j]=0;
}
}
cout<<ans[m]<<endl;
}
}