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的次数,以及所有移动的总步数。


输入描述:

仅一行,输入一个正整数 n ( 1 n 60 ) n(1 \leq n \leq 60) 表示汉诺塔的层数。


输出描述:

首先输出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);
}
发布了162 篇原创文章 · 获赞 99 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Q_1849805767/article/details/104229728