jzoj 6797. 【2014廣州市選day2】hanoi

Sport_River發表於2020-09-12

Description

你對經典的hanoi塔問題一定已經很熟悉了。有三根柱子,n個大小不一的圓盤,要求大盤不能壓在小盤上,初始時n個圓盤都在第一根柱子上,最少要多少步才能挪到最後一根柱子上?
現在我們來將hanoi塔擴充套件一下,由三根柱子擴充套件到四根柱子,其餘規則不變。例如,3個圓盤,四根柱子A到D,初始時圓盤都A柱上,我們用五步就可以將圓盤都挪到D柱上:
第一步:將圓盤1從A挪到B;
第二步:將圓盤2從A挪到C;
第三步:將圓盤3從A挪到D;
第四步:將圓盤2從C挪到D;
第五步:將圓盤1從B挪到D。
你的任務是寫一個程式求解四柱子hanoi塔問題最少要多少步可以解決。

Input

輸入只有一行,為一個正整數n。(1<=n<=1000)

Output

輸出為一個正整數,代表n盤四柱子hanoi塔問題最少要多少步可以解決。

Solution

在做經典漢諾塔問題的時候,我們是用遞推求出n個盤子時的步數的,我們做這道題的時候也就類比,嘗試是否能夠遞推解決問題
以下是前10個數的表

盤子數 步數
1 1
2 3
3 5
4 9
5 13
6 17
7 25
8 33
9 41
10 49
... ...

觀察上面的表格,我們發現,從1個盤子到2個盤子與2個到3個各增加了2步即\(2^{1}\)步;從3個到4個、從4個到5個與從5個到6個各增加了4步即\(2^{2}\)步,以此類推,我們做出猜想

\[f_{i}=f_{i-1}+2^{k} \]

其中\(k \in N^{*}\)且是遞增的
對於\(2^{k}\)會加(k+1)次
資料\(n \leqslant 1000\)所以直接遞推就好

#include <cstdio>
#include <algorithm>
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int n,cnt,num,i;
long long add,f[1001];
int main()
{
    open("hanoi");
    scanf("%d",&n);
    f[1]=1;f[2]=3;f[3]=5;
    add=4;cnt=3;num=3;
    for (i=4;i<=n;i++)
    {
        f[i]=f[i-1]+add;
        cnt--;
        if (!cnt) cnt=++num,add*=2;
    }
    printf("%lld",f[n]);
    return 0;
}

相關文章