title: ACM-NEFUOJ-汉诺塔问题
tags:

  • ACM
  • NEFUOJ
    abbrlink: 2cb26a25
    date: 2020-12-19 15:11:33

P200汉诺塔

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int main()
  4. {
  5. int n,i;
  6. long long s[40];
  7. s[1]=2;
  8. for(i=2;i<=35;i++)
  9. s[i]=3*s[i-1]+2;
  10. while(cin>>n)
  11. cout<<s[n]<<endl;
  12. return 0;
  13. }

P201又见汉诺塔

引用一波qky大佬的思路

在题目要求条件下,将n个盘子从左边移动到最右边的最快方法是:

(1)先将n-1个盘子移动到中间

(2)让最大的盘子直接移动到最右边(2步)

(3)最后再让n-1个盘子移动到最右边

(1)和(3)最需步数应该是一样的,且因为只有最大的盘子才能放在其他盘子上面,所以计算(1)(3)的步骤数时不需考虑这一特殊要求;

我用near数组来储存(1)(3)所需的步骤,计算需要递归;n个盘子从左边移动到中间步骤如下:

(1)先让n-1个盘子移动到最右端

(2)让最大的盘子移动到中间

(3)让n-1个盘子从右端移动到中间

(1)的话和200题一样的;(3)的话就是递归;

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. long long han[21];
  4. long long near[21];
  5. void prepare(){
  6. han[1]=2;
  7. for(int i=2;i<=20;i++)
  8. han[i]=3*han[i-1]+2;
  9. near[1]=1;
  10. for(int i=2;i<=20;i++)
  11. near[i]=han[i-1]+near[i-1]+1;
  12. }
  13. long long fun(int n){
  14. if(n==1)
  15. return 2;
  16. else
  17. return 2*near[n-1]+2;
  18. }
  19. int main(){
  20. prepare();
  21. int T;
  22. cin>>T;
  23. while(T--){
  24. int n;
  25. cin>>n;
  26. cout<<fun(n)<<endl;
  27. }
  28. return 0;
  29. }