例如:
5 = 1+1+1+1+1
5 = 1+1+1+2
5 = 1+1+2+1
5 = 1+2+1+1
5 = 2+1+1+1
5 = 1+2+2
5 = 2+2+1
5 = 2+1+2
有没有人可以给出一个伪代码的提示,说明如何完成这个任务呢? 老实说,我连从哪里开始都不知道。 此外,这看起来像是一个指数问题,能不能用线性时间解决呢?
谢谢。
例如:
5 = 1+1+1+1+1
5 = 1+1+1+2
5 = 1+1+2+1
5 = 1+2+1+1
5 = 2+1+1+1
5 = 1+2+2
5 = 2+2+1
5 = 2+1+2
有没有人可以给出一个伪代码的提示,说明如何完成这个任务呢? 老实说,我连从哪里开始都不知道。 此外,这看起来像是一个指数问题,能不能用线性时间解决呢?
谢谢。
F(n)
为用 1 和 2 写成的 n
的方式数量。那么最后一个加数要么是 1 要么是 2。因此 F(n) = F(n-1) + F(n-2)
。这些是初始值:F(1) = 1 (1 = 1)
F(2) = 2 (2 = 1 + 1, 2 = 2)
double factorial(int n)
{
if (n <= 0)
return 1;
else
return n * factorial(n - 1);
}
std::round(std::tgamma(n + 1)); // where n >= 0
double permutation(int n, int k)
{
return factorial(n) / factorial(n - k);
}
double combination(int n, int k)
{
return permutation(n, k) / factorial(k);
}
int solve(int n)
{
double result = 0;
if (n > 0) {
for ( int k = 0; k <= n; k += 1, n -= 1 )
result += combination(n, k);
}
return std::round(result);
}
int fibonacci(int n)
{
constexpr double SQRT_5 = std::sqrt(5.0);
constexpr double GOLDEN_RATIO = (SQRT_5 + 1.0) / 2.0;
return std::round(std::pow(GOLDEN_RATIO, n) / SQRT_5);
}
int solve(int n)
{
if (n > 0)
return fibonacci(n + 1);
return 0;
}
这个问题可以很容易地可视化如下:
考虑一只青蛙,它在一个楼梯前面。它需要到达第n
级台阶,但它每次只能跳1或2个台阶。找出它可以到达第n
级台阶的方式数量?
让T(n)
表示到达第n
级台阶的方法数。
所以,T(1)
=1
,T(2)
=2
(两个一步跳或一个两步跳,总共2种方式)
为了到达第n
级台阶,我们已经知道了到达第(n-1)
级台阶和第(n-2)
级台阶的方法数。
因此,人们可以通过从(n-1)
级台阶进行1步跳或从(n-2)
级台阶进行2步跳来简单地到达第n
级台阶...
T(n)
= T(n-1)
+ T(n-2)
。这里是使用回溯法解决您的问题的代码。在每一步中,记住用于得到当前总和的数字(在这里使用向量),首先复制它们,然后从n中减去1并将其添加到副本中,然后使用n-1和添加了1的向量副本进行递归,并在n==0时打印。然后返回并重复相同的步骤以2为基础,这本质上就是回溯。
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
int n;
void print(vector<int> vect){
cout << n <<" = ";
for(int i=0;i<vect.size(); ++i){
if(i>0)
cout <<"+" <<vect[i];
else cout << vect[i];
}
cout << endl;
}
void gen(int n, vector<int> vect){
if(!n)
print(vect);
else{
for(int i=1;i<=2;++i){
if(n-i>=0){
std::vector<int> vect2(vect);
vect2.push_back(i);
gen(n-i,vect2);
}
}
}
}
int main(){
scanf("%d",&n);
vector<int> vect;
gen(n,vect);
}