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\n",f[i]);
return 0;
}

原文地址:https://www.cnblogs.com/little-cute-hjr/p/12388762.html

时间: 2024-08-08 05:57:07

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

POJ1958 Strange Towers of Hanoi --- 递推【n盘m塔Hanoi塔问题】

POJ1958 Strange Towers of Hanoi Sol: n盘4塔问题可以分为3步: 1.以4塔模式移走i个盘. 2.以3塔模式将剩余n-i个盘移至第4塔. 3.以4塔模式将第一步中的i个盘移至第4塔. 我们用\(d[i]\)表示在3塔模式下移i个盘的最小步数,\(f[i]\)表示在4塔模式下移i个盘的最小步数. 递推式:\(f[i]=\min_{1\leq j < i}(2*f[j]+d[i-j])\) EX 本题可以拓展至n盘m塔问题. \(f[i][j]\)表示在i塔模式下

Gym10081 A - Arcade Game -康托展开、全排列、组合数变成递推的思想

最近做到好多概率,组合数,全排列的题目,本咸鱼不会啊,我概率论都挂科了... 这个题学到了一个康托展开,有点用,瞎写一下... 康托展开: 适用对象:没有重复元素的全排列. 把一个整数X展开成如下形式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0![1] 其中a[i]为当前未出现的元素中是排在第几个(从0开始),并且0<=a[i]<i(1<=i<=n) 用来求全排列中这个串排第几,康托展开的逆运算就是

山区建小学(区间型动态规划,递推)

描述政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m.为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 ).请根据给定的m.n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值.输入第1行为m和n,其间用空格间隔第2行为(m-1) 个整数,依次

数的计数(noip2001,动态规划递推)

题目链接: 普通版: https://www.luogu.org/problemnew/show/P1028 数据加强版: https://www.luogu.org/problemnew/show/P2240 中间插一段,奇怪了,我明明想到的是最好的那种递推方法,结果写着写着忘记了,写成最差的递推方法 所以中间插一段被我遗忘的好方法 这个也是这题的书上的答案 #include<bits/stdc++.h> using namespace std; int a[1001]; int main(

[题解][SHOI2013]超级跳马 动态规划/递推式/矩阵快速幂优化

这道题... 让我见识了纪中的强大 这道题是来纪中第二天(7.2)做的,这么晚写题解是因为 我去学矩阵乘法啦啦啦啦啦对矩阵乘法一窍不通的童鞋戳链接啦 层层递推会TLE,正解矩阵快速幂 首先题意就是给你一个 n 行m 列 的格子图 一只马从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行. 题意很简单暴力dp的思路也很简单但是数据很恶心虽然远古一点,但毕竟是省选题 1 ≤ n ≤ 50,2 ≤ m ≤ 10^9 不过还是给了我们一点提示:n这么小? 总之我们先找出转移式对于每一个点

[P1192]台阶问题 - 动态规划 - 递推

https://www.luogu.org/problemnew/show/P1192 题目描述 有N级的台阶,你一开始在底部,每次可以向上迈最多K级台阶(最少1级),问到达第N级台阶有多少种不同方式. 输入输出格式 输入格式: 输入文件的仅包含两个正整数N,K. 输出格式: 输入文件stair.out仅包括1个正整数,为不同方式数,由于答案可能很大,你需要输出mod 100003后的结果. 输入输出样例 输入样例#1:复制 5 2 输出样例#1:复制 8 说明 对于20%的数据,有N ≤ 10

【动态规划/递推】BZOJ1806[IOI2007]- Miners

[思路] 用1.2.3分别代替三种食物,0表示当前矿井没有食物.f[i][a][b][c][d]当前第i个食物,矿1的食物顺序由上至下为a,b:矿2的食物顺序由上至下为c,d. 判断产物数量的方法很巧妙,由下至上a,b,c.初始时默认投入一个食物至少生产一单位,如果a为有食物且与bc不同,则加一单位:如果b为有食物且与c不同,再加一个单位.最后加一个滚动数组就可以了. [错因] 1.因为a,b,c,d大小范围是0..3,但是我把下标范围写3!一定要写4!我就是一不小心写错了,居然改了两个晚上,完

判断整除(动态规划,递推)

总时间限制: 1000ms 内存限制: 65536kB 描述 一个给定的正整数序列,在每个数之前都插入+号或-号后计算它们的和.比如序列:1.2.4共有8种可能的序列: (+1) + (+2) + (+4) = 7 (+1) + (+2) + (-4) = -1 (+1) + (-2) + (+4) = 3 (+1) + (-2) + (-4) = -5 (-1) + (+2) + (+4) = 5 (-1) + (+2) + (-4) = -3 (-1) + (-2) + (+4) = 1 (

[POJ1958]Strange Towers of Hanoi (递推)

POJ炸了 所以放这里来 #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #include<algorithm> #include<iostream> #define max(