递归问题|汉诺塔|数学归纳法

子曰:“君子周而不比,

小人比而不周。”

君子是团结到周围的同学但是不勾结,小人是勾结别人但是不团结。

本文讲述了递归文章中的汉诺塔问题。

我们需要注意如何拆解成为一个更小的问题。

构造汉诺塔的最优策略以及最小步骤。

通过一种错误的归纳证明强化数学归纳法的理解。

使用一种格雷码的状态存储汉诺塔的状态,并且分析移动过程中的性质。

什么是递归,每个问题的解都依赖于同一问题的更小实例的解。

图片

汉诺塔游戏是这样的游戏

我们需要将左边的塔移动到最右边的塔,每次只能移动一个圆盘,且较大的圆盘在移动过程中不能放置在较小的圆盘上面。

和图片上不一样的是,汉诺塔是64个圆盘。

我们的问题是:最好的解法是上面,要完成这项任务移动多少次才是必须且必须的。

解决这样问题的最好办法就是对他稍加推广。汉诺塔有64个,我们认为有n个圆盘。

这样的好处就是,大大简化问题。因为n不固定,我们就可以使用比较小的塔了。

解决下一个问题就是引入适当的记号:命名并且求解。

图片

图片

图片

图片

图片

我们有一种策略是:

1将n-1个圆盘移到另外一个圆盘上。

2将最底下的盘子移到想要移动的盘子上。

3将n-1个盘子移到想要移动的盘子上。

这样肯定是可以,也就是我们得到了。

图片

那么有没有更快的方法?

没有,因为把第n个圆盘移到终点,一定要将其他的n-1个圆盘移到过渡点,如果不这样一定完不成。

将第n个圆盘移到终点,然后将n-1个圆盘从过渡点移到终点。

图片

图片

这个式子有边界值,也有两两之间的关系。

但是递归式知识给出间接、局部的信息。

但是我们想要得到一目了然的解,也就是我们想要知道有一种封闭形式-闭公式,使得我们可以快速计算,并且理解最小移动次数的特征。

T[1]=1

T[2]=3

T[3]=7

T[4]=15

T[5]=31

T[6]=63

T[7]=127

T[8]=255

T[9]=511

T[10]=1023

图片

图片

图片

华罗庚先生说:“设想一下,如果这个飞跃现象不出现,那么人们一辈子就只能学数数了,而且人生有限,数目无穷,就是学了一辈子,也绝不会学尽呢!”

图片

在《具体数学》中生成我们经过了三个阶段。

(1)研究小的情形,这有助于我们洞察该问题,而且对第二和第三阶段有所帮助。

(2)对有意义的量,求出数学表达式,并且给出证明。对汉诺塔,就是递归式,

图片

(3)对数学表达式求出粉笔形式,并且给予证明,对于汉诺塔,就是递归解。

图片

其实我们可以通过高中的知识进行求解,

图片

#include <bits/stdc++.h>using namespace std;#define int long longint n;int f[100010];void dfs(int l,int r,int mid,int n){  if(n==1)  {    printf("%d->%d\n",l,r);//只执行一步     return ;  }  dfs(l,mid,r,n-1);//将n-1个圆盘移动到过渡点   printf("%d->%d\n",l,r);//将最底下的元素移到终点   dfs(mid,r,l,n-1);//将n-1个圆盘移动到过渡点。 }  signed main(){   dfs(1,3,2,5); }

所有的马都是有相同的颜色的吗?

=

图片

图片

图片

图片

如果最左边不能直接移动到最右边。

图片

如果在这种限制的条件下,我们会在3根柱状上都遇到n个圆盘的每一种正确地叠放。

图片

图片

是否存在n个圆盘在3根柱子上,以某种开始叠放或结束叠放,使得按照卢卡斯原来的规则,需要多于2^n次移动?

图片

由此可以看出,原来的放置方法就是最困难的放置方法。

图片

这就是斐波那契数列,但是要加上高精度。

图片

图片

但是这题需要使用高精度。

#include<bits/stdc++.h>using namespace std;struct big{  vector<int>d;  big()  {      }  big(int w)  {    while(w)    {      d.push_back(w%10);      w/=10;    }  }  big(string s)  {    for(int i=s.size()-1;i>=0;i--)        d.push_back(s[i]-'0');  }  int &operator[](int id)  {    return d[id];  }  size_t size()  {    return d.size();  }  void push(int t)  {    d.push_back(t);  }  void pop()  {    d.pop_back();  }  bool operator<(big b)  {    if(size()!=b.size())    {      return size()<b.size();    }    for(int i=size()-1;i>=0;i--)    {      if(d[i]!=b[i])return d[i]<b[i];    }    return false;  }  bool operator>(big b)  {    return b<*this;  }  bool operator<=(big b)  {    return !(*this>b);  }  bool operator>=(big b)  {    return !(*this<b);  }};big operator+(big a,big b){  if(a.size()<b.size())  return b+a;  big c;  int t=0;  for(int i =0;i<a.size();i++)  {    t+=a[i];    if(i<b.size())t+=b[i];    c.push(t%10);    t/=10;  }  if(t)c.push(t);  return c;}big operator-(big &a,big&b){  big c;  for(int i=0,t=0;i<a.size();i++)  {    t=a[i]-t;    if(i<b.size())t-=b[i];    c.push((t+10)%10);    if(t<0)t=1;    else t=0;  }  while(c.size()>1&&c.d.back()==0)  {    c.pop();  }  return c;}big operator*(big &a,int b){  big c;  int t=0;  for(int i=0;i<a.size()||t;i++)  {    if(i<a.size())t+=a[i]*b;    c.push(t%10);    t/=10;  }  while(c.size()>1&&c.d.back()==0)c.d.pop_back();  return c;}big operator*(big &a,big &b){  int sz=a.size()+b.size()+1;  big res;  res.d.resize(sz);  for(int i=0;i<a.size();i++)  {    for(int j=0;j<b.size();j++)    {      res[i+j]+=a[i]*b[j];    }  }  for(int i=0;i<sz;i++)  {    res[i+1]+=res[i]/10;    res[i]%=10;  }  for(;res.d.back()==0&&res.size()>=2;)  {    res.d.pop_back();  }  return res;}pair<big,int>div(big&a,int b){  big c;  int r=0;  for(int i=a.size()-1;i>=0;i--)  {    r=r*10+a[i];    c.push(r/b);    r%=b;  }  reverse(c.d.begin(),c.d.end());  while(c.size()>1&&c.d.back()==0)c.pop();  return {c,r};}big operator/(big &a,int b){  return div(a,b).first;}int operator%(big &a,int b){  return div(a,b).second;}signed main(){  big now(1),pre(1);  int n;  cin>>n;  for(int i=1;i<=n-1;i++)  {    auto tmp=now;    now=now+pre;    pre=tmp;  }  for(int i=now.size()-1;i>=0;i--)  {    cout<<now[i];  }}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值