题目链接1:分苹果
题目描述:
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。输入第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。输出对输入的每组数据M和N,用一行输出相应的K。样例输入1 7 3样例输出
8
思路:
一种dfs的搜索算法,和拆分数相似(拆分的代码在下面)
code:
#include<iostream>
using namespace std;
int n,m;
int tatal,temp;//记录总数与分成了几个
void dfs(int,int);//循环函数
int main()
{
int t;
cin>>t;
while(t--)//几次
{
tatal=0;//一定要归零
temp=0;
cin>>m>>n;
dfs(1,m);//开始循环
cout<<tatal<<endl;
}
return 0;
}
void dfs(int t,int s)
{
for(int i=t;i<=s;++i)
{
++temp;//记录分成了几个
s-=i;//减去分出去的
if(s==0&&temp<=n)//是否分到最后和个数书否允许
++tatal;
else
dfs(i,s);//继续循环
s+=i;//回溯,加上减去的数,以便寻找所有的的情况
--temp;//表示这一步不需要
}
}
题目链接:自然数的拆分问题
题目描述:
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。
输入格式:
一个待拆分的自然数n。
输出格式:若干数的加法式子。
输入样例
7
输出样例
1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4
code:
#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
int a[10001]={1},n;//初始a[0]=1;
void search(int,int);
void print(int);
int main()
{
cin>>n;
search(n,1);
//将要拆分的数n传递给s
return 0;
}
void print(int t)
{
for (int i=1;i<=t-1;i++)
//输出一种拆分方案
cout<<a[i]<<"+";
cout<<a[t]<<endl;
}
void search(int s,int t)
{
for (int i=a[t-1];i<=s&&i<n;i++)
//当前数i要大于等于前1位数,且不过n
{
a[t]=i;//保存当前拆分的数i
s-=i; //s减去数i, s的值将继续拆分
if(s==0)
print(t); //当s=0时,拆分结束输出结果
else
search(s,t+1); //当s>0时,继续递归
s+=i; //回溯:加上拆分的数,以便产分所有可能的拆分
}
}