随意翻论坛,翻到巨人网络的一道笔试题,感觉很熟悉。想到在CSDN遇到过。这两道题很相似,也很简单,都能很容易的想到动态规划递归,然后将其改成非递归实现提高效率。
分巧克力
题意大概是一块长度为n的巧克力,每次可以在边上砍去一段,这段的长度可以是1,也可以是2,问最后有多少种砍法?
显然是f(n)=f(n-1)+f(n-2),f(0)=1,f(1)=1,类似与斐波那契数列啊
代码:
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Test {
public:
static long long pre (int x){
/*递归方法
if(1==x)return 1;
if(2==x)return 2;
return pre(x-1)+pre(x-2);
*/
//将递归改写为非递归
if(1==x)return 1;
if(2==x)return 2;
long long x1=1,x2=2,x3=0;
for(int i=3;i<=x;++i){
x3=x1+x2;
x1=x2;
x2=x3;
}
return x3;
}
};
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main(){
cout<<Test::pre(50)<<endl;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
非递归实现辅助空间是2,因为只跟前两项有关。
巨人网络笔试题--上台阶
1, 假设A上台阶,一次可以跨1层,2层或3层,问A上50层台阶,有多少种走法?
假设A上台阶,一次可以跨1层,2层,3层.. 或m层,问A上n层台阶,有多少种走法?
其中,m和n都是正整数,并且 m <= n, m <= 10, n <= 50
请编程解决这个问题,并详细说明解题思路。
同样可以通过f(x)=f(x-1)+f(x-2)....+f(x-m),f(0)=1,f(1)=1;
可以通过递归和非递归实现,非递归实现的辅助空间为o(m),因为跟前m项相关,代码如下:
#include <iostream>
#include <vector>
int getNum1(int n,int m){
if(0==n)
return 1;
int ret=0;
int max=n>=m?m:n;
for(int i=1;i<=max;++i)
ret+=getNum1(n-i,m);
return ret;
}
int getNum2(int n,int m){
/*这里为了简单使用了n个辅助空间,当然可以通过循环使用m个辅助空间*/
std::vector<int>*ret=new std::vector<int>(n+1);
(*ret)[0]=1;
for(int i=1;i<=n;++i){
int max=m<=i?m:i;
for(int j=1;j<=m&&j<=i;++j){
(*ret)[i]+=(*ret)[i-j];
}
}
return (*ret)[n];
}
int main(int argc,char**argv){
std::cout<<getNum1(3,2)<<std::endl;
std::cout<<getNum2(3,2)<<std::endl;
std::cout<<getNum1(10,3)<<std::endl;
std::cout<<getNum2(10,3)<<std::endl;
return 0;
}
优化
可以通过下面来减少加法次数:
f(x+m)=f(x+m-1)+....+(fx)
f(x+m+1)=f(x+m)+f(x+m-1)+....+(fx+1) =2*f(x+m)-f(x)=(f(x+m)<<1)-f(x)来优化