【台阶方案】
#include <iostream>
using namespace std;
#define LL long long
const int N=1e6+5;
const LL p=1e9+7;
LL dp[N];
int a[3];//
int main()
{
LL n;
cin>>n;
cin>>a[0]>>a[1]>>a[2];
dp[0]=1;//当目标值为 0 时,只有一种方案
for (int i=1;i<=n;++i)
{
for (int j=0;j<3;j++)
{
if (i-a[j]>=0)
dp[i]=(dp[i]+dp[i-a[j]])%p;
}
}
cout<<dp[n];
return 0;
}
n = 5
a[0] = 1 a[1] = 2 a[2] = 3 dp[0]=1 dp[1,2,3…]=0
首先,初始化 dp[0] = 1
。从 1 开始循环到 5,对于每个位置 i
,根据步长数组 a
来更新 dp[i]
的值。
当 i = 1
时:
- 对于
j = 0
,i - a[j] = 1 - 1 = 0
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[0] = 0+ 1 = 1
。
当 i = 2
时:
- 对于
j = 0
,i - a[j] = 2 - 1 = 1
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[1] = 1
。 - 对于
j = 1
,i - a[j] = 2 - 2 = 0
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[0] = 2
。
当 i = 3
时:
- 对于
j = 0
,i - a[j] = 3 - 1 = 2
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[2] = 2
。 - 对于
j = 1
,i - a[j] = 3 - 2 = 1
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[1] = 3
。 - 对于
j = 2
,i - a[j] = 3 - 3 = 0
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[0] = 4
。
当 i = 4
时:
- 对于
j = 0
,i - a[j] = 4 - 1 = 3
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[3] = 4
。 - 对于
j = 1
,i - a[j] = 4 - 2 = 2
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[2] =6
。 - 对于
j = 2
,i - a[j] = 4 - 3 = 1
,所以dp[i] = dp[i] + dp[i - a[j]] = dp[i] + dp[1] = 7
。
通过动态规划的思想将步长和方案数进行了关联。对于每一个位置 i,通过遍历步长数组 a 中的每一个值,来计算当前位置 i 的方案数 dp[i]。
假设当前要计算的位置是 i,那么遍历步长数组 a 中的每一个步长 a[j],如果 i - a[j] >= 0,说明当前位置可以由之前的某个位置经过步长 a[j]到达,此时就累加上到达该位置的方案数 dp[i-a[j]] 到当前的方案数 dp[i] 中。这样就能够实现将步长和方案数进行关联,动态地计算出每个位置的方案数。
当 n 的值为 0 时,for (int i=1; i<=n; ++i) 不会执行任何循环,而 for (int i=1; i<n; i++) 会执行一次循环。取决于具体需求,选择适当的循环条件。