题解 | #循环汉诺塔#

循环汉诺塔

https://www.nowcoder.com/practice/cdf0808f841748faba058c8ef538c731

#include<iostream>
#include<vector>

using namespace std;
// 以下是@Muuuuuuu的解题思想,仅做借鉴学习*****************
//根据题目规定,易知该情况下,只有底部,没有顶部,从A移动到B需要1次操作(A→B),从A移动到C需要2次操作(A→B,B→C)。

//设函数AB(N)为把N个盘从A移动到B需要操作的次数,函数AC(N)为把N个盘从A移动到C需要操作的次数。

// 因此我们可以记为当N=1时,AB(1)=1,AC(1)=2。
//A移动到B时
/*首先需要把顶部从A移到C,再把底部从A移到B,最后把顶部从C移到B。

一共会有5次操作,即1、A→B,2、B→C,3、A→B,4、C→A,5、A→B。

实际上,AB(N)可以视为是由3个子问题组成的,即1、顶部移动两次,2、底部移动一次,3、顶部移动两次;

子问题1实际上是AC(N-1)的问题;

子问题2由于底部只有一个盘,所以子问题2的值恒等于AB(1),即值为1;

子问题3实际上也是AC(N-1)的问题;

所以AB(N)=AC(N-1)+1+AC(N-1)

简化一下,AB(N)=2AC(N-1)+1*/

/*A移动到C时:
首先将顶部从A移到C,再将底部从A移到B,再将顶部从C移到A,再将底部从B移到C,最后将顶部从A移到C。

一共有7次操作,即:1、A→B,2、B→C,3、A→B,4、C→A,5、B→C,6、A→B,7、B→C。

同样的,AC(N)也可以视为由5个子问题组成,即:1、顶部移动两次,2、底部移动一次,3、顶部移动一次,

4、底部移动一次,5、顶部移动两次;

子问题1实际上是AC(N-1)的问题;

子问题2由于底部只有一个盘,所以子问题2的值恒等于AB(1),即值为1;

子问题3实际上是AB(N-1)的问题;

子问题4也是值恒为1;

子问题5实际上也是AC(N-1)的问题;

所以AC(N)=AC(N-1)+1+AB(N-1)+1+AC(N-1)

简化一下,AC(N)=2AC(N-1)+AB(N-1)+2*/

void RecurHanoi(int index, int n, vector<long long int> &AB, vector<long long int> &AC){
    //index = 2 初始化使用该函数
    // AB[1] = 1, AC[1] = 2;
    if(index > n){
        return;
    }
    // AB[n] = 2*AC[n-1] + 1
    // AC[n] = 2*AC[n-1] + AB[n-1] + 2
    // 这里注意要先取模,要不会数据太大,会出现负数
    AB[index] = (2*AC[index-1] + 1)%1000000007;
    AC[index] = (2*AC[index-1] + AB[index-1]  + 2)%1000000007;
    index++;
    RecurHanoi(index, n, AB, AC);
}

int main(){
    int n = 0;
    cin >> n;
    int id = 2;
    vector<long long int> AB(n+1, 1);
    vector<long long int> AC(n+1, 2);
    RecurHanoi(id, n, AB, AC);
    cout << AB[n] << ' ' << AC[n] << endl;
    return 0;
}

#解题#
全部评论

相关推荐

点赞 评论 收藏
分享
想润的芹菜人狠话不多:把其中一个老总放中间都会得罪另一个
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务