Prob.2[动态规划+递推+划归思想的应用]POJ 1958 Strange Towers Of Hanoi Upd:2020.3.1

Posted little-cute-hjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Prob.2[动态规划+递推+划归思想的应用]POJ 1958 Strange Towers Of Hanoi Upd:2020.3.1相关的知识,希望对你有一定的参考价值。

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

汉诺塔:https://www.cnblogs.com/antineutrino/p/3334540.html

问题引入:这个在标准的三塔问题上又加了一维,我们先考虑三个塔是怎么计算的?可以具体地分成三个步骤:

1.假设A塔上有n个盘子,将A塔上n-1个盘子转移到B塔上。

2.将A塔上剩余的一个盘子转移到C塔上。

3.将B塔上剩余的n-1个盘子转移到C塔上

因为后转移的盘子小,上面n-1个盘子都能落在上面,2之后的C柱可以看成空的柱子,于是1、3两步中的最小移动数相等。

设d[i]表示将i个盘子从A移动到C的方案数。B、C等效,于是d[n]=2*d[n-1]+1,两次1、3,最下方移动+1即可,线性递推不难。

由此可见,我们将n个盘子的移动,转化为了n-1个盘子的移动,进一步可以转化成n-2,n-3,n-4....3,2,1 这其实就是程序的递归/递推逻辑。

现在,让我们考虑四个柱子。一样是尝试着划归

首先,我们用四根柱子的方法,将A柱上的k个盘子转移到B柱上。然后由于B柱上所有的盘子都比A小,对于A柱剩余的n-k个盘子来说,B柱相当于没有。问题转化为了

三根柱子的问题!!于是我们用三根柱子的方法移动A柱上n-k个盘子,然后再用四根柱子的方法移动B上的k个盘子到D柱上,问题解决!

设f[i]表示i个盘子的方案数,d[i]同上。

由此,我们得到状态转移方程:

f[n]=min{2*f[k]+d[n-k]} k∈{1,2,.....n}

进一步,我们考虑m个柱子,n个盘子的情况。对于所有m个盘子,都可以先将其转化为m-1个盘子的情况,然后进行计算!上式依然成立,只不过f数组记录m个柱子的数据,d数组记录m-1个柱子的数据。

多么巧妙的递推!

AC代码:

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
ll d[13],f[120];
inline ll min(ll x,ll y)
{
return x<y?x:y;
}
int main()
{
memset(f,0x3f,sizeof(f));
f[1]=1;
d[1]=1;
for(int i=2;i<=13;i++)
d[i]=2*d[i-1]+1;
// printf("%d",d[n]);
for(int i=1;i<=12;i++)
for(int j=1;j<=i;j++)
f[i]=min(f[i],2*f[j]+d[i-j]);
for(int i=1;i<=12;i++)
printf("%lld ",f[i]);
return 0;
}

以上是关于Prob.2[动态规划+递推+划归思想的应用]POJ 1958 Strange Towers Of Hanoi Upd:2020.3.1的主要内容,如果未能解决你的问题,请参考以下文章

算法之动态规划(递推求解一)

动态规划——递推求解

动态规划——递推求解

01背包和动态规划

[LeetCode] 动态规划入门题目

Python|最大子序和