20天集训——day6

今天讲的是递归,我一直分不出递归和递推的区别。递归算法的出发点不放在初始条件上,放在求解的目标上,从所求的未知项出发逐次调用本身的求解过程,直到递归的边界(即初始条件)。而递推是

递推算法是直接从一个容易解决的小问题出发,递进地求解规模越来越大的问题,直到初始问题被解决,只经过了由小到大的问题解决过程,并且这一过程一般是直线式的,中途没有反复。

递归的效率较差。但好像比较好理解。

结构:

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;
}

猜你喜欢

转载自blog.csdn.net/wangzhuojia/article/details/80975539
今日推荐