Namomo spring camp 2022 Div.2
Day.2
题目描述
楼梯有 n 阶,上楼可以一步上一阶,也可以一步上二阶。但你不能连续三步都走两阶,计算走到第n阶共有多少种不同的走法。
输入格式
一行,一个数字,表示n。
输出格式
输出走楼梯的方式总数。
数据规模
对于 100 100 100% 的数据,保证 n ≤ \le ≤ 50。
样例输入
6
样例输出
12
题目释义
有一次上 1 or 2 个阶梯两种走法,不能有连续三次上 2 步,求上到第 n 个阶梯有多少方案
算法设计
(不会的方法)心路历程:最开始我认为,加的这个限制条件会对后续处理有影响,而不能用dp。
(但是我不会别的方法的)为了求证,我又看了一遍无后效性的解释
无后效性是指如果在某个阶段上过程的状态已知,则从此阶段以后过程的发展变化仅与此阶段的状态有关,而与过程在此阶段以前的阶段所经历过的状态无关。利用动态规划方法求解多阶段决策过程问题,过程的状态必须具备无后效性。1 (查阅自百度百科)
我突然觉得还是可以用dp的。
算法选择
动态规划
前面说了那么多,我自然首选dp。(实际上我也不知道也还算不算dp)
根据最基础的 走楼梯 问题,假设走到第 i 阶楼梯的方案数为 f[i],我们知道:
f[i] = f[i-1] + f[i-2]; (i >= 2)
想要走到 i,只能从 i-1 走一步,或者从 i-2 走两步上来。这就是了两个(最优)子结构。
而在不能连续三次两步的限制下。
我们认为 f[i-1]
与 f[i-2]
都满足此要求。那么就只有最后三步会出现走连续三次两阶的情况。
由此分析:
- 第三次,必然是从
f[i-2]
跳到f[i]
- 第一、二次,必然是到
f[i-2]
时连续走了两次两阶
- 由 1、2 我们知道,只需从
f[i-2]
中,减去 最后两次都是二阶的情况 即可。
到这里我以为就结束了,因为 最后两次都是二阶的情况 不就是 f[i-2-4]
的方案数吗?
所以答案是?:
f[i] = f[i-1] + f[i-2] - f[i-6]; 吗?
(在我题解提交并WA了之后)仔细分析之后,我发现并非如此。
因为对于 f[i-6]
依然存在最后走 0/1/2 个两阶的情况。
- 因此我们只需要把
f[i-6]
中最后一步是走两阶的情况去掉即可。即把从f[i-6-2]
到f[i-6]
的情况去掉,就只剩下f[i-6-1]
即f[i-7]
了。
所以我们的答案就是:
f[i] = f[i-1] + f[i-2] - f[i-7];
数据处理
定义全局变量 n 和 f* (可自动赋初值)
int n;
long long f[51];
初始化:
f[0] = 1;
f[1] = 1;
算法逻辑
- i ≤ \le ≤ 5 时,不存在三次两阶的情况。
- i == 6 时,f[i-7] 依然不存在,但是有连续三次两阶的情况,特殊处理。
- i ≥ \ge ≥ 7 时,满足状态转移方程。
for(int i = 2; i <= n; i++) {
if(i >= 7)
f[i] = f[i-1] + f[i-2] - f[i-7];
else if(i == 6)
f[i] = 12;
else
f[i] = f[i-1] + f[i-2];
}
陈克式,陈开周.经济 数学辞典:中国经济出版社,1991年09月第1版 ↩︎