递归(Hanoi、放苹果)

目录

 

汉诺塔

题意:

思路:

代码:

放苹果

思路:

特殊情况:

终止条件:

代码:


汉诺塔

 

网图:https://www.zhihu.com/question/24385418

题意:

汉诺塔是一种古老的游戏。 一共3个柱子,标号为1,2,3 1号柱子有从大到小一共n个盘子。

每次移动最上方的一个盘子,可以移动到其他的柱子。 任何一个盘子,都不能叠在比它更小的盘子的上方。 请把盘子从1号柱子,全部移动到3号柱子。

思路:

只有一个的时候: 从A—>C即可。

只有两个的时候:先将最上面从A-->B,再将最大的从A—>C,再将B的移到C。

三个的时候:先将最上面两个用上面最有两个的情况移动到B中,此时C为中转柱,B为目标柱。再将最大的也就是第三个从A—>C,再将B的两个同样方式由B出发移动到C。

(步数最小原因:若想最大的先进入C,只能让上面的两个进入B腾出位置,也就是对应两个的时候,然后再将B的两个移动到C,由此也可推出dp[i]=2*dp[i-2]+1);

……

N个的时候,先将上面的(n-1)移动B,然后再将第N个移动到C,再将B的(n-1)个移动到C。而(n-1)如何移动在上面已经递推出,也就是也N的移动方式、思维方式想用,不同的只是起始柱、中转柱、目标柱的不同。进而得到递归的核心思想:分解。把一个很复杂的问题使用同一个策略将其分解为较简单的问题,如果这个的问题仍然不能解决则再次分解,直到问题能被直接处理为止。

dfs(n,A,B,C)

         下层递归dfs(n-1,A,C,B);-----此处可加语句记录路径,也就是那个移动起始柱最下面的-----------------------printf("Move %d from %c to %c\n",n,A,C);-------dfs(n-1,B,A,C);

终止条件,n==1的时候 printf("Move %d from %c to %c\n",n,A,C); return;

代码:

#include<bits/stdc++.h>

//dp[i] = dp[i-1]*2+1;  dp[i-1]从1-->2  2-->1分别为dp[i-1]次 所以为2倍,然后加上最大块从1-->3;

using namespace std;

void dfs_hanoi(int n,char a,char b,char c){

         if(n == 1){

                  printf("Move 1 from %c to %c\n",a,c);

                  return ;

         }

         dfs_hanoi(n-1,a,c,b);

         printf("Move %d from %c to %c\n",n,a,c);

         dfs_hanoi(n-1,b,a,c);

}

int main(){

         int n;

         cin >> n;

         dfs_hanoi(n,'1','2','3');

         return 0;

}

放苹果

思路:

分情况考虑,因为无顺序可言,对某一个盘子放与不放意义不大。对全放和至少一个不妨考虑。

dfs(m,n)   如果至少一个不放,就是dfs(m,n-1),否则就先都放上一个dfs(m-n,n);这样就转化为目前为止的n中至少一个放超过一个,

特殊情况:

n>m 肯定有n-m空盘子,因为不考虑顺序,此时=dfs(m,m);

终止条件:

n==1||m==0即只剩下一个盘子全放里面和没有剩下的苹果剩下的盘子都不放,return 1;

代码:

#include<algorithm>

#include<iostream>

#include<cstring>

#include<string>

#include<cstdlib>

#include<map>

#include<cmath>

#include<vector>



using namespace std;

typedef long long ll;

const int maxn = 1e6+50;

int dfs(int m,int n){

         if(n==1||m==0)   return 1;

         if(n > m)    return dfs(m,m);

         return dfs(m,n-1)+dfs(m-n,n);

}

int main(){

         int m,n;

         int t;

         cin >> t;

         while(t--){

                  cin >> m >> n;

                  cout << dfs(m,n) << endl;    

         }

         return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值