CSP历年复赛题-P1096 [NOIP2007 普及组] Hanoi 双塔问题

原题链接:https://www.luogu.com.cn/problem/P1096

题意解读:汉诺双塔的移动次数,与经典汉诺塔的区间在于同一个尺寸盘子有两个。

解题思路:

可以直接用经典汉诺塔方法来计算,双塔的结果就最终乘以2即可。

首先想到的是递归,但是由于数据量n最大200,递归会超时,但是50%的样例应该没问题,先拿分!

50分代码:

#include <bits/stdc++.h>
using namespace std;

int ans;

void hanoi(int n)
{
    if(n == 1)
    {
        ans++; //只剩一个盘子,移动到目标柱子
        return;
    }
    hanoi(n-1); //移动前n-1个盘子都暂存柱子
    ans++; //移动第n个到目标柱子
    hanoi(n-1); //移动前n-1个到目标柱子
}

int main()
{
    int n;
    cin >> n;
    hanoi(n);
    cout << ans * 2; //双塔乘以2

    return 0;
}

根据提示,考虑采用递推,直接借助上面递归代码运行出

n = 1,输出2

n = 2,输出6

n = 3,输出14

n = 4,输出30

n = 5,输出62

我们观察一下2,6,14,30,62,可以推出递推式f[n] = f[n-1] * 2 + 2,初始值f[1] = 2,最终结果是f[n]

由于n最大是200,2^200用long long也无法存储,需要高精度

先写出以下代码,再替换高精度

70分代码:

#include <bits/stdc++.h>
using namespace std;

long long f[205];

int main()
{
    int n;
    cin >> n;
    f[1] = 2;
    for(int i = 2; i <= n; i++)
    {
        f[i] = f[i-1] * 2 + 2;
    }
    cout << f[n];

    return 0;
}

加上高精度,只需要加法即可!

100分代码:

#include <bits/stdc++.h>
using namespace std;

vector<int> f[205];
vector<int> g2(1, 2); //高精度的2

vector<int> add(vector<int> &a, vector<int> &b)
{
    vector<int> res;
    int t = 0;
    int len = max(a.size(), b.size());
    for(int i = 0; i < len; i++)
    {
        if(i < a.size()) t += a[i];
        if(i < b.size()) t += b[i];
        res.push_back(t % 10);
        t /= 10;
    }
    if(t) res.push_back(t);
    return res;
}

int main()
{
    int n;
    cin >> n;
    f[1] = g2;
    for(int i = 2; i <= n; i++)
    {
        vector<int> res = add(f[i-1], f[i-1]);
        f[i] = add(res, g2);
    }
    
    for(int i = f[n].size() - 1; i >= 0; i--) cout << f[n][i];

    return 0;
}

 

posted @ 2024-05-27 11:20  五月江城  阅读(97)  评论(0编辑  收藏  举报