POJ1958:Strange Towers of Hanoi

我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html

题目传送门:http://poj.org/problem?id=1958

题目要我们求四柱汉诺塔的步数最小值,将盘子数在$1$到$12$之间的全部求出来。

状态空间即为移动盘子对应的步数。

对于三柱汉诺塔,相信大家都非常熟悉了。我们假设三柱汉诺塔上有$n$个盘子,$f[n]$表示将$n$个盘子移动到另一根柱子上的最小步数,那么显然:

$f[n]=f[n-1]*2+1$

就相当于你先把上面$n-1$个盘子先移到第二跟柱子上,然后用一步把最后的大盘子移动到第三根柱子上。再把那$n-1$个盘子移到第三根柱子上。

那么在题目要求的四柱条件下,状态就可以用三柱条件下的状态扩展得来。设$g[n]$表示四柱条件下$n$个盘子从第一根全部移到另一根的最小步数。

那么显然:

$g[n]=min${$\sum_{i=1}^{n-1}g[i]*2+g[n-i]$}

就是枚举先将$i$个盘子移动到另一根柱子上,然后将剩下的盘子在三柱条件下移动到最后一根柱子上,再将先前的$i$根柱子移动到最后一根柱子上去。

时间复杂度:$O(n^2)$

空间复杂度:$O(n)$

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int n=12;
int f[13],g[13];

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

int main() {
    memset(g,63,sizeof(g));
    g[1]=1;
    for(int i=1;i<=n;i++)
        f[i]=f[i-1]*2+1;
    for(int i=2;i<=n;i++)
        for(int j=1;j<i;j++)
            g[i]=min(g[i],g[j]*2+f[i-j]);
    for(int i=1;i<=n;i++)
        printf("%d\n",g[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKMer/p/9625746.html