问题描述:现在有15个苹果,每次至少吃3个请问有多少种吃法?
这类问题的关键是要找到递推关系,即前一个状态与后一个状态的关系。
现在设f(n)表示有n个苹果时的吃法数量,那么在第一次吃苹果后,我们可以得到如下等式:
进一步我们可以到如下的递推关系式:
因此我们可以编写相应的递归程序来处理这个问题:
long eatApples_Recursive(int num)
{
if(num<=3)
return 1;
else
{
long sum =0;
for (int i=3;i<=num;++i)
{
sum += eatApples_Recursive(num-i);
}
return sum;
}
}
经分析我们可以知道这样一个递归程序的时间复杂到了0(2^n)指数级的,在这个递归程序中存在很多的重复的计算,下面采用动态规划对程序进行优化。
long eatApples_DP(int num)
{
long *memoArray = new long[num+1];
for (int i=0;i<=num;++i)
{
if(i<=3)
memoArray[i] = 1;
else
{
memoArray[i] = 0;
for (int j=3;j<=i;++j)
{
memoArray[i] += memoArray[i-j];
}
}
}
return memoArray[num];
}
这样程序的时间复杂度就降到了0(n)。
下面是完整的测试程序
#include <iostream>
using namespace std;
long eatApples_Recursive(int num)
{
if(num<=3)
return 1;
else
{
long sum =0;
for (int i=3;i<=num;++i)
{
sum += eatApples_Recursive(num-i);
}
return sum;
}
}
long eatApples_DP(int num)
{
long *memoArray = new long[num+1];
for (int i=0;i<=num;++i)
{
if(i<=3)
memoArray[i] = 1;
else
{
memoArray[i] = 0;
for (int j=3;j<=i;++j)
{
memoArray[i] += memoArray[i-j];
}
}
}
return memoArray[num];
}
int main()
{
cout<<"Please input the number of the apples: ";
int num = 0;
cin>>num;
cout<<endl;
cout<<"The number of different eating method:"<<eatApples_Recursive(num)<<endl;
cout<<"The number of different eating method:"<<eatApples_DP(num)<<endl;
system("pause");
return 0;
}