第【7】章: 数递归、DFS、剪枝、回溯等问题 学习报告
(7.2)节: 递归问题
1.题干:
递归方便表达,但是性能上消耗过多
1、有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶、3阶。 请实现一个方法,计算小孩有多少种上楼的方式。
为了防止溢出,请将结果Mod 1000000007
给定一个正整数int n,请返回一个数,代表上楼的方式数。
保证n小于等于100000。
1、关键代码1:
int k2(int n)
{int rte=0;
if(n==1)
return 1;
if(n==2)
return 2;
if(n==3)
return 4;
return (k2(n-1)+k2(n-2)+k2(n-3))%1000000007;
}
关键代码2:
int k2(int n)
{
int a[n+2];
int k;
a[0]=0;a[1]=1;a[2]=2;a[3]=4;
if(n==0)
k=0;
else if(n==1)
k=1;
else if(n==2)
k=2;
else if(n==3)
k=4;
else
for(int i=n;i<=n;i++)
{a[i]=(a[i-1]% 1000000007+a[i-2]% 1000000007+a[i-3])%1000000007;
k=a[i];
}
return k;
}
关键代码3:
int k2(int n)
{int k=0;
if(n==0)
return 1;
if(n==1)
return 1;
if(n==2)
return 2;
if(n==3)
return 4;
int x1=1;
int x2=2;
int x3=4;
for(int i=4;i<=n;i++)
{int x_1=x1;
x1=x2;
x2=x3;
x3=x_1%1000000007+x2%1000000007+x1%1000000007;
k=x3%1000000007;
}
return k;
}
(7.3)节: 机器人走方格
1.题干:有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。 请设计一个算法,计算机器人有多少种走法。
给定两个正整数int x,int y,请返回机器人的走法数目。
保证x+y小于等于12。
2、解答思路:从一开始找规律
3、关键代码1:
int k1(int x,int y)
{if(x==1||y==1)
return 1;
return k3(x-1,y)+k3(x,y-1);
}
关键代码2:
int k2(int x,int y)
{int a[x+1][y+1];
for(int i=1;i<=y;i++)
a[1][i]=1;
for(int i=1;i<=x;i++)
a[i][1]=1;
for(int i=2;i<=x;i++)
for(int j=2;j<=y;j++)
a[i][j]=a[i-1][j]+a[i][j-1];
return a[x][y];
}
(7.4)节: 硬币表示
1、题干:假设我们有8种不同面值的硬币{1,2,5,10,20,50,100,200},用这些硬币组合够成一个给定的数值n。 例如n=200,那么一种可能的组合方式为 200 = 3 1 + 1*2 + 1*5 + 2*20 + 1 50 + 1 * 100. 问总共有多少种可能的组合方式?
2、解答思路:通过对靠近x的值进行分解,然后递归进行下一步分解
3、关键代码:
int a[8]={1,2,5,10,20,50,100,200};
int k3(int a[],int k,int x)//a为存储面值的数组,k为数组个数,x为给定数值n
{
if(x<=0)//刚好为倍数
return 1;
if(k==0)//只有一种走法;
return 1;
int max=0;
for(int i=0;i*a[k]<=x;i++)
{
max+=k3(a,k-1,x-i*a[k]);
}
return max;
}
int main()
{
int a[8]={1,2,5,10,20,50,100,200};
cout<<k3(a,8,10)<<endl;
return 0;
}