2020牛客寒假算法基础集训营3——I.牛牛的汉诺塔记忆化

Posted Nirvana柒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020牛客寒假算法基础集训营3——I.牛牛的汉诺塔记忆化相关的知识,希望对你有一定的参考价值。


​题目传送门​


题目描述

汉诺塔是一个经典问题,相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置n个金盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。

汉诺塔以及其衍生问题往往使用递归来求解,也是学习和理解递归很好的老师。

其伪代码如下

Function Hanoi(n,a,b,c)
if n==1 then
print(a+->+c)
else
Hanoi(n-1,a,c,b)
print(a+->+c)
Hanoi(n-1,b,a,c)
end if
end Function

牛牛很快就理解了代码的意思并且写出了求解汉诺塔的程序,他现在想研究汉诺塔的规律。
请你统计以下信息:A->B,A->C,B->A,B->C,C->A,C->B的次数,以及所有移动的总步数。


输入描述:

仅一行,输入一个正整数 2020牛客寒假算法基础集训营3——I.牛牛的汉诺塔【记忆化】_汉诺塔


输出描述:

首先输出6行
A->B:XX
A->C:XX
B->A:XX
B->C:XX
C->A:XX
C->B:XX
分别表示每种移动情况出现的次数
最后输出一行
SUM:XX
表示所有移动情况的总和。


输入

3


输出

A->B:1
A->C:3
B->A:1
B->C:1
C->A:0
C->B:1
SUM:7


说明

伪代码所示算法的移动序列如下:
A->C
A->B
C->B
A->C
B->A
B->C
A->C
统计:
A->B出现1次
A->C出现3次
B->C出现1次
B->A出现1次
C->B出现1次
总计7次


题解

  • 很熟悉的题目,递归 + 记忆化即可

AC-Code

#include<bits/stdc++.h>
using namespace std;
struct node
long long data[6];
node()
memset(data, 0, sizeof(data));

//A->B 0
//A->C 1
//B->A 2
//B->C 3
//C->A 4
//C->B 5
;

node operator + (const node& A, const node& B)
node C;
for (int i = 0; i < 6; ++i)
C.data[i] = A.data[i] + B.data[i];
return C;


void moveto(int x, int y, node& temp)
if (x == 0 && y == 1) ++temp.data[0];
else if (x == 0 && y == 2) ++temp.data[1];
else if (x == 1 && y == 0) ++temp.data[2];
else if (x == 1 && y == 2) ++temp.data[3];
else if (x == 2 && y == 0) ++temp.data[4];
else if (x == 2 && y == 1) ++temp.data[5];


node dp[3][3][3][105];
bool vis[3][3][3][105];

node hanoi(int a, int b, int c, int n)
if (vis[a][b][c][n]) return dp[a][b][c][n];
if (n == 1)
moveto(a, c, dp[a][b][c][n]);
vis[a][b][c][n] = true;
return dp[a][b][c][n];

node temp;
temp += hanoi(a, c, b, n - 1);
moveto(a, c, temp);
temp += hanoi(b, a, c, n - 1);
vis[a][b][c][n] = true;
return dp[a][b][c][n] = temp;


int main()
int n; cin >> n;
node ans = hanoi(0, 1, 2, n);
printf("A->B:%lld\\n", ans.data[0]);
printf("A->C:%lld\\n", ans.data[1]);
printf("B->A:%lld\\n", ans.data[2]);
printf("B->C:%lld\\n", ans.data[3]);
printf("C->A:%lld\\n", ans.data[4]);
printf("C->B:%lld\\n", ans.data[5]);
printf("SUM:%lld\\n", (1LL << n) - 1);


以上是关于2020牛客寒假算法基础集训营3——I.牛牛的汉诺塔记忆化的主要内容,如果未能解决你的问题,请参考以下文章

2020牛客寒假算法基础集训营5.J——牛牛战队的秀场

2020牛客寒假算法基础集训营2——C.算概率DP

2020牛客寒假算法基础集训营5.A——模板简单计算

2020牛客寒假算法基础集训营5.C——C语言IDE超级大模拟

2020牛客寒假算法基础集训营6.C——汉诺塔贪心 & Dilworth定理 & 二分求上升子序列最小化分数

2022牛客寒假算法基础集训营1全部题解