递推算法是直接从一个容易解决的小问题出发,递进地求解规模越来越大的问题,直到初始问题被解决,只经过了由小到大的问题解决过程,并且这一过程一般是直线式的,中途没有反复。
递归的效率较差。但好像比较好理解。
结构:
void rec(形参列表)
{
if(test) return ;//边界条件
rec(实参列表) //递归调用
语句序列2 //递归返回段(回溯)
}
今天刷了5道题(上课讲的)。
第一题:整数划分将n分为x个数的和。问有几种分法。
#include<bits/stdc++.h>
using namespace std;
int f(int n,int m)//n为剩下的数,m为最大加数
{
if(n==0 || m==0) return 0;
if(n==1 || m==1) return 1;
if(n<m) return f(n,n);
if(n==m) return f(n,n-1)+1;
else
return f(n,m-1)+f(n-m,m);
}
int main()
{
int x,y;
cin>>x;
y=f(x,x);
cout<<y;
return 0;
}
第二题:计算w到p的方案数。 这题数据很大,所以要用空间换时间的方法用记忆化搜索。
#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,l=0;
int c[1100000]={};
int h(int k)
{
if(c[k]>=0) return c[k];//记忆化,若c以搜索过就直接返回值
if(k==m) return 1;
if(k<m) return 0;
c[k]=h(k-a)+h(k-b);
return c[k];
}
int main()
{
cin>>n>>m>>a>>b;
memset(c,-1,sizeof(c));
c[m]=1;
cout<<h(n);
}
第三题:n个人传球,传m此后又回到第一个人手中,球可以左右传,问有几种传法。
#include<bits/stdc++.h>
using namespace std;
int n,m,l=0;
int a[50][50];
int h(int x,int y)//k为传球的次数,y为在哪个人的手中
{
if(a[x][y]>=0) return a[x][y];//由于是环,要分类讨论
if(x==m)//到边界
{
if(y==1) return 1;//传到第一个人手中输出方案数
return 0;//没到第一个人手中
}
if(y==1)
{
a[x][y]=h(x+1,n)+h(x+1,2);//第n个人向左给n-1,向右给1;
}
else
if(y==n)
{
a[x][y]=h(x+1,n-1)+h(x+1,1);
}
else
{
a[x][y]=h(x+1,y-1)+h(x+1,y+1);
}
return a[x][y];
}
int main()
{
cin>>n>>m;
memset(a,-1,sizeof(a));
a[m][1]=1;
cout<<h(0,1);
return 0;
}