正好做到这里,觉得这题有点儿意思,也复习到以前写的一些算法题目,于是我就想把我的思路放在这,仅供参考。
先说两个名词:
第一个是斐波那契数列;
第二个是字符串加法;
说到这是不是有点思路了呢?
题目如下:
一只小蜜蜂在如下图所示的蜂窝上爬行。它爬行时,只能从一个格爬到相邻的大号格子中。例如,从 1 号格子可以爬到 2 号或者 3 号格子,从 2 号则可以爬到 3 号或者 4 号格子。
请问从一个格子 a 爬到一个格子 b 一共有多少种可行的路线。
输入:
分别是起始点 a 和终止点 b 的编号。( a 和 b 在 1~100 之间,且 a<b 。)
输出:
方案数量。
首先是斐波那契数列,不难发现,起点与终点两个数字输入后,总满足他们之间的差值正好是斐波那契数列中的某一项,这里不过多赘述,可以自己尝试一下。
然后是字符串加法,从实例中不难发现,当输入1和100的时候,位数达到了惊人的21位,而最大的long long类型也只能存储20位数据,这个时候就需要利用字符串进行所谓的加法操作。
这里给出主要算法,一个是斐波那契数列的递归,一个是字符串加法的实现。
warning:我要开始加难度了。
一、字符串加法
说到加法,我们不妨回忆一下小时候学的竖式加法,尾数对齐,满十进一什么的马上就想到了吧!好了,我们要开始实现了:
由于是要对字符串不断加法,我们需要返回一个字符串的指针,方便多次调用和操作。
malloc:在内存堆区开辟一段存储空间,由于是堆区,就可以在函数结束的时候不至于被系统删除,具体声明格式可以自己搜索和学习,这里不多说(我说的不好,没有其他大佬说得好)
整体算法难度不大,可以自己调试一下,摸索一下。
char* solve(char* s, char* t )
{
int lens = strlen(s);
int lent = strlen(t);
int lenresult = (lens > lent ? lens : lent) + 2; // 这里加二,创建一头一尾多两个位置
int curresult = lenresult - 1; // 一来字符结尾的\0,二来首位可能进一
int temp, flag = 0;
char* result = (char*)malloc(sizeof(char) * (lenresult));
result[curresult] = 0; // 字符里面的0其实就是\0
while(lens || lent)
{
temp = flag; // 后一位的进一,继承到前一位计算
// 如果没有进一,那就是0,也是一种初始化
if(lent)
{
temp += t[--lent] - '0'; // 过渡到整数的运算
}
if(lens)
{
temp += s[--lens] - '0';
}
flag = temp / 10; // 逢十进一
temp %= 10; // 得到尾数存储入字符串
result[--curresult] = temp + '0'; // 将整数返还给字符形式 ,存储入字符串
}
result[0] = flag + '0'; // 这里得到最高位的数字,用于继承到字符串首位
return flag ? result : result + 1;
// 如果最高位还进一了,那就返回字符串首地址,如果没有,返回下一位
}
二、斐波那契数列
由于是字符串的加法,我们所有的加法结果都存储在字符串里面,那好,斐波那契数列怎么让他循环计算值。
打表?我叭叭给你两拳
不妨考虑这样一个点,F(n+2)=F(n+1)+F(n),如果保持前后的关系,利用一个循环,问题就解决了,算法如下:
很精简,很优雅。
int a=1; // 第一项
int b=1; // 第二项
int c=0; // 循环项
while(n--)
{
c=a+b;
a=b;
b=c;
}
到这里,字符串怎么计算,等来等去的字符串可不行。
现在再介绍一个函数:strcpy。
函数作用就是:复制字符串
将源所指向的 C 字符串复制到目标所指向的数组中,包括终止空字符(并在该点停止)。
稍微调整一下上面循环的代码,于是就可以得到下面这个算法
int a=0;
int b=0;
scanf("%d %d",&a,&b);
char res[30]="1";
int n=b-a-1;
char arr[30]="1";
char brr[30]="1";
while(n--)
{
strcpy(res,solve(arr,brr)); // solve函数返回的也是一个指针
strcpy(arr,brr);
strcpy(brr,res);
}
总结:
这道题的关键就是字符串加法这个做法,其次的斐波那契数列只是在字符串的基础上增加了一些新的花样。