题目:http://poj.org/problem?id=1664
Description
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
Input
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
Output
对输入的每组数据M和N,用一行输出相应的K。
Sample Input
1 7 3
Sample Output
8dfs:每回递归判断重复太傻了,可以有规律的找,每次让后面的比前面的大即可。
//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int dfs(int m,int n,int pre){
int cnt=0; //开始写错了,应该是数第一次循环返回的个数
if(n==1)
return 1;
for(int i=pre;i<=m/n;i++){
cnt+=dfs(m-i,n-1,i);
}
return cnt;
}
int main(){
int t,m,n;
cin>>t;
while(t--){
cin>>m>>n;
cout<<dfs(m,n,0)<<endl;
}
return 0;
}
dp:dp[i][j]为n个盘子放m个苹果,可以拆为:4个苹果放6个盘子相当于4个盘子放4个苹果dp[i][j]=dp[j][j],
6个苹果放4个盘子相当于6个苹果放3个盘子,加上每个盘子都放了一个再放2个,就是2个苹果放4个盘子。
#include<bits/stdc++.h>
using namespace std;
int dp[15][15];
int main(){
int n,m,t;
fill(dp[0],dp[0]+15*15,1);
for(int i=2;i<15;i++)
for(int j=2;j<15;j++)
if(i>j)
dp[i][j]=dp[j][j];
else
dp[i][j]=dp[i-1][j]+dp[i][j-i];
cin>>t;
while(t--){
cin>>m>>n;
cout<<dp[n][m]<<endl;//n个盘子放m个苹果
}
return 0;
}
母函数:
和楼梯问题(砝码称重)的例子不同,这里和贴邮票类似,有无穷多个数可用,但做法和01背包变多重背包相似,
多加一个k循环即可。
#include<iostream>
using namespace std;
int c1[105],c2[105];
int main(){
int t,n,m;
cin>>t;
while(t--){
cin>>n>>m; //n分为m份
for(int i=0;i<=n;i++){
c1[i]=1;
c2[i]=0;
}
for(int i=2;i<=m;i++){ //表示第i个括号(表达式)
for(int j=0;j<=n;j++) //更新系数,指数为j+k时的系数
for(int k=0;k+j<=n;k+=i) //i=2时,好几个(1+x^2)往里加
c2[j+k]+=c1[j];
for(int j=0;j<=n;j++){
c1[j]=c2[j];
c2[j]=0;
}
}
cout<<c1[n]<<endl;
}
return 0;
}