有 N 级台阶,你一开始在底部,每次可以向上迈 1∼K 级台阶,问到达第 N 级台阶有多少种不同方式。输入N K。输出正整数(mod 100003)为到达N阶台阶的方法。
首先对于一个编程问题我们要对其的思考要有以下几个步骤
目录
1 对问题的整体思考
2 思考内容的数学化转化
3 数学思想转变为编程思想的实现
动态规划方法
1 台阶问题实质就是斐波那契数列进阶(斐波那契详细请看)
根据分类计数原理,按照最后一次上台阶的阶数分类,可为N-1次时上一阶,N-2次时上两节……最多到N-K次时上K阶,于是第N次的方法就为N-1,N-2,……,N-K次之和;此方法需要计算出每一阶的方法数
2 思考内容的数学化,写为函数的形式就是F(N)=F(N-1)+F(N-2)+……F(N-k) ;且F(1)=1
3 最后的也是最复杂的(bushi)就是编程化
本篇递推主要以循环为主
首先需要定义数组,容纳每一阶的方法数量int arr[100000];
然后初始化一下
for (i = 2; i <= N; i++) i递推自增直至为所求值N(大概的将i看成N),(第一阶仅有一种,从第二阶开始,因此i=2)
for (j = 1; j <= K && j < i; j++) j递推自增直至为K,由于N>K,所以必须保证i>j;
接下来还需要对K和i的大小进行比较,其意义是,能否从0阶直接达到N阶,当i<=K时即可以从0阶达到目标阶(这样就多一种从0到N),否则不可(初始的值就为0)。
然后递增 arr[i] += arr[i - j];
最后不要忘记取模
主体完成大概是这样
#include <stdio.h>
int cls(int N, int K)
{
int arr[N];//数组arr[N]表示到n有几种解法
int i, j;
for (i = 0; i <= N; i++)
{
arr[i] = 0;//初始化数组
}
arr[1] = 1;
//最底层不动一种方法是循环的初始值
for (i = 2; i <= N; i++)
{
if(i<=K)arr[i] = 1;//可从0阶到达目标阶
for (j = 1; j <= K && j < i; j++)
{
arr[i] += arr[i - j];
}
arr[i] %= 100003;
}
return arr[N];
}
而主函数便相对简单
int main()
{
int N, K;
int ret;
scanf_s("%d %d", &N, &K);
ret = cls(N, K);
printf("%d", ret);
}
总结:因为为int类型所以可能会出现溢出的情况,是一种常用的处理台阶问题的方法
DFS算法
算法介绍具体为
其主要的操作位循环+回溯+计数(计数步省略了)
首先仍然定义数组,将数组的每一位元素定义为1一直到第N位,代表一次上一个台阶的那一种方式,这就是第一个if()所执行的,采用N--的方式直到N==0进入到最后的if()中对方法计数
然后向前回溯一个格(index--两次抵消第一个if里的++,回退一格),判断既不等于0也不等于K,进入else result[index]变为2 一次上两个台阶 总和不变仍为N
index++之后指向下一位的0,判断成立进入else 计数加一 同时再往前回退一位
……
直至回退到N-K时,判断是否已经index已经为0(即判断是否到达第一步),当没有在第一步
将K变为0;同时+K变为原来的N并指向前一位
进行判断1!=0||K,进入else中,1++,指向下一步,判断得0;
进入第一个if变为0自增为1;指向下一步;
……直至满足和为N
当第一个值为K时,index=0;break;
(这里可能图有误差但第一个是K这个意思大差不差,初学也不太懂)
结束循环
#include <stdio.h>
int taiJie(int N, int K)
{
int result[100000] = { 0 };//代表第index步走的台阶数,也就是方块中的数字
int index = 0;//index其实指的是步数,也就是图中的方块
int counter = 0;//用来计数
while (1)
{
if (result[index] == 0) {
result[index] = 1;
N -= 1;
index++;
}
else if (result[index] == K)
{
if (index == 0)break;
result[index] = 0;
N += K;
index--;
}
else {
result[index]++;
N -= 1;
index++;
}
if (N == 0)
{
counter++;
index--;
N += result[index];
result[index] = 0;
index--;
}
}
return counter;
}
void main()
{
int N,K;
scanf("%d %d", &N, &K);
printf("%d\n", taiJie(N, K));
}
总结 这也是很多dalao可能会想到的方法,但是计算量有点大,简单计算没问题,复杂计算可能会出现超时的情况,总而言之也是一种算法
完结撒花
❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀
❀❀❀❀❀❀❀❀❀❀❀ ( emm...排版目录还不太能用明白) ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀