每日一题:走楼梯2

.走楼梯2 - 题目 - Daimayuan Online Judge

先来看一下简单版的走楼梯

走楼梯,我们要从下往上走,每跨一步只能向上走1级或者2级台阶,问一共有多少种走法

给定一座有10级台阶的楼梯

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
int n;
LL f[51];
int main()
{
    cin >> n;
    f[0] = 1, f[1] = 1;
    for (int i = 2; i <= n; i++) {
        f[i] = f[i - 1] + f[i - 2];
    }
    cout << f[n] << endl;
    return 0;
}

而该题在简单版走楼梯的基础上加了不能连续三步都走两阶这一限制条件,因此需要再加一维,用来表示走到该层楼梯连续走了几个两步)(指的是从第i层往前连续地推,有几个连续的两阶)(只要保证走到i层楼梯不是连续走三个两阶到的就行(i是任意的))

初始化(别一开始就写,先写转移方程,等写好后根据需要来初始化)

f[0][0]=1 f[1][0]=1 f[1][1]=0 f[1][2]=0

等于1的初始化一下,而等于0的就不用管了,外部变量初始就是0

状态转移:

f[i][0]表示从i-1层走一阶到第i层的,所以f[i][0]就可以由f[i-1][0]+f[i-1][1]+f[i-1][2]转移过来,因为走到i-1层完全可以走两个两阶,这样是满足没有直接的走两阶到i层的

f[i][1]表示走了一个两阶到i层的,所以就等价于f[i-2][0]

f[i][2]表示连续走了两个两阶到i层的,就等价于从i-1层走一个两阶到i层,即f[i-1][1]

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define int  long long 
const int N = 110;
int f[N][3];
signed main()
{
    int n;
    cin >> n;
    f[0][0] = f[1][0] = 1;
    for (int i = 2; i <= n; i++) {
        f[i][0] = f[i - 1][0] + f[i - 1][1] + f[i - 1][2];
        f[i][1] = f[i - 2][0];
        f[i][2] = f[i - 2][1];
    }
    cout << f[n][0] + f[n][1] + f[n][2] << endl;
}

至于为什么f[2][2]=f[0][1]是可以这样推的,到第二层最多只能走一个两阶,所以f[2][2]应该等于0,实际上f[0][1]也等于0,所以没关系 

补充:

每日一题:走楼梯2,动态规划,之前写的题解是初始化了f[0][0],其实并不好理解,其实完全可以让递推的那个循环从3开始,然后把需要用到的初始化,这样就不需要f[0][0]了,这样的话就都是根据实际意义来,就很好理解

问题出在状态转移上,没搞清楚f[i][0],f[i][1],f[i][2]的意义,f[i][0]是到i用了一个一阶,然后它可以从i-1阶到i阶,而到i-1阶可以用1步,用一个二阶,也可以用连续两个二阶

f[i][1]表示到i阶就是用了一个二阶,即从i-2阶到i阶,所以到i-2阶只能用一个一阶

f[i][2]表示到i阶用了连续两个二阶,即从i-4阶到i-2阶,再从i-2阶到i阶

就是一开始写递推循环的时候先随便比如说从1开始,然后递推式写好后,再调整保证需要初始化的量第一维是从1开始的,这样初始化的时候就直接根据实际意义来初始化

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int N=110;
int f[N][3];//f[i][0]表示最后走到i用了一个一阶,f[i][1]表示最后走到i用了一个两阶,f[i][2]表示最后走到i用了连续的两个两阶
void solve()
{
	int n;
	cin>>n;
	//初始化
	f[1][0]=1;
	f[2][0]=1;
	f[2][1]=1;
	for(int i=3;i<=n;i++){
		f[i][0]=f[i-1][1]+f[i-1][2]+f[i-1][0];
		f[i][1]=f[i-2][0];
		f[i][2]=f[i-2][1];
	}
	cout<<f[n][0]+f[n][1]+f[n][2]<<endl;
}
signed main()
{
	solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值