先来看一道题:洛谷P2386
把 m 个同样的苹果放在 n 个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法。(5,1,1 和 1,1,5 是同一种方法)
输入格式
第一行是测试数据的数目 tt,以下每行均包括二个整数 mm 和 nn,以空格分开。
输出格式
对输入的每组数据 mm 和 nn,用一行输出相应的结果。
输入输出样例
输入 #1
1 7 3
输出 #1
8
输入 #2
3 3 2 4 3 2 7
输出 #2
2 4 2
说明/提示
对于所有数据,保证:1≤m,n≤10,0≤t≤20 。
有的神犇的代码:
//摘要题解:
#include<bits/stdc++.h>
using namespace std;
int m,n,ans,f[15][15];//f[i][j]即为i个苹果放在j个盘子里的方案数
int main()
{
int t;
cin >> t;
while(t--)//t组测试数据
{
cin >> m >> n;
ans=0;//ans置0
memset(f,0,sizeof(f));//清空f数组
for(int i=1;i<=n;i++)
f[0][i]=f[1][i]=1;//当苹果数量是1或0时,永远只有一种方法
for(int i=1;i<=m;i++)
f[i][1]=1;//当只有一个盘子的时候,永远只有一种方法
for(int i=2;i<=m;i++)
for(int j=2;j<=n;j++)
if(i<j)//如果苹果比盘子还少
f[i][j]=f[i][i];//等于i个苹果放在i个盘子里
else
f[i][j]=f[i-j][j]+f[i][j-1];//对于每一次,有两种做法:
//1:j个盘子里都放 1个,即 f[i-j][j]
//2:都不放,即 f[i][j-1]
cout << f[m][n] << endl;//输出
}
return 0;
}
看着似乎有点麻烦。
这时,我们引进一个新的函数——递归函数。
含义:
一种计算过程。,如果其中每一步都要用到前一步或前几步的结果,就称为递归。
用递归过程定义的函数,称为递归函数。//by某度
大白话说,递归就是将一个大问题转化成许多个小问题,再将许多个小问题转化成许多个小小问题,再将许多个小小问题转化成许多个小小小问题……(其实这段话也可以用递归打出来QAQ)
递归是一种很重要的算法,像汉诺塔等皆需用到递归。
放开头那道题的代码(详解):
#include<bits/stdc++.h> //万能头文件
using namespace std;
int n,a[25],b[25];
int f(int x,int y){ //定义递归函数
if(x==1||y==1){ //记忆化搜索:如果已经计算过,那么直接加上结果就行
return 1;
}
if(x<y){ //当苹果数小于盘子数时
return f(x,x); //计算结果和“苹果数和盘子数相等时”的情况一样。
}
if(x>y){ //当苹果数大于盘子数时
return f(x-y,y)+f(x,y-1); //分成两种情况,一种是每个盘子中放一个苹果,另一种是一个盘子不放苹果。
}
if(x==y){ //当相等时
return 1+f(x,y-1); //那么就是一个盘子不放苹果的情况数再加上1
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
cout<<f(a[i],b[i])<<endl; //调用函数
}
return 0;
}
递归是一种函数(不是数学的那个),很重要。如果这里学不会,基本上和信息学就无缘了。