您的位置:首页 > 其它

hanoi塔问题的自己的理解及相关竞赛题的解答

2018-01-27 13:38 507 查看
  昨日学习python时一时兴起,决定将hanoi塔问题用python写一遍,然后觉得这个问题实在是太有趣了,搞懂了
一个最经典的便可举一反三,以往在比赛中遇到的hanoi问题都可迎刃而解。以下便是总结:(假设从左到右柱子分别为
a, b, c)
 1、最经典:
当只有一个石块时,只需要从a->c.两个石块时,第一个石块a->b,然后第二个石块a->c,最后b->c.后面都是一样的道理,不管多少块,完成都必定经过上面n-1个在b上,然后将最后一个从a->c。最后将n-1个移到c上。n块从a->c需要b的协助,n-1的a->b需要c的协助,便可使用递归!便有以下python代码def move(*s):
print(s[0], "移动到", s[1])

def simpleHanoi(n, a, b, c):
if n == 1:
move(a,c)
else:
simpleHanoi(n-1,a,c,b)
move(a,c)
simpleHanoi(n-1,b,a,c)

simpleHanoi(4, 'A', 'B', 'C') c++:
#include<iostream>

using namespace std;

void move(char from, char to) {
cout << from << "移动到" << to << endl;
}

void hanoi(int n, char from, char dependOn, char to) {
if (n == 1)
move(from, to);
else {
hanoi(n - 1, from, to, dependOn);
move(from, to);
hanoi(n - 1, dependOn, from, to);
}
}

int main(){
hanoi(5, 'A', 'B', 'C');
return 0;
}
2、进阶版, 每次只能移到相邻的柱子上:
这个步骤和上面的不太一样,但原理基本相同。基本步骤就是n-1个两步移到c然后最后一个移到b,然后n-1移到a,最后一个移到c然后n-1移到c大功告成,了解这个就可以写代码了(c++的懒得写了/笑哭):def move(*s):
if len(s) == 2:
print(s[0], "移动到", s[1])
elif len(s) == 3:
print(s[0], "移动到", s[1])
print(s[1], "移动到", s[2])

def hanoi(n = 1, a = 'A', b = 'B', c = 'C'):
if n == 1:
move(a,b,c)
else:
hanoi(n-1,a,b,c)
move(a,b)
hanoi(n-1,c,b,a)
move(b,c)
hanio(n-1,a,b,c)

hanoi(3)
3、接着就是各种题目了!hdu上的2064 汉诺塔III:我本来的代码:#include<iostream>

using namespace std;

int num;

void hanoi(int n) {
if (n == 1)
num += 2;
else {
hanoi(n - 1);
num++;
hanoi(n - 1);
num++;
hanoi(n - 1);
}
}

int main() {
int n;
while (cin >> n && n) {
num = 0;
hanoi(n);
cout << num << endl;
}
a51c
return 0;
}可是n<35, 肯定超时啦!此时假设步骤中移动上面n-1个盘子到c盘要t(n-1)的步数第n个移动到b1步此时为t(n-1)+1然后移n-1回a 此时2t(n-1)+1移中间的第n块要1步即2t(n-1)+ 2最后完成最后t(n - 1)步为t(n) = 3*t(n-1) + 2;故而有:#include<iostream>

using namespace std;

int main() {

int n;
while (scanf("%d", &n)!=EOF) {
long long ans = 2;
for (int i = 2; i <= n; i++)
ans = 3 * ans + 2;
cout << ans << endl;
}
return 0;
}然后就是这道题:N阶汉诺塔变形要知道这个题目是要实时监控步数的变化的,到步数时就立马收集答案,而步数改变的地方只有move函数,故有上面的代码更改为:#include<iostream>
#include<string.h>
#include<stack>

using namespace std;

stack<int> p[4];
stack<int> ans[4];
bool flag;

void moveone(int &k, int from, int to) {
if (flag)return;
p[to].push(p[from].top());
p[from].pop();
if (k == 1)
flag = true;
else k--;
}

void hanoi(int n, int a, int b, int c, int &k) {
if (flag || k == 0) {
for (int i = 1; i <= 3; i++)
while (!p[i].empty()) {
ans[i].push(p[i].top());
p[i].pop();
}
return;
}

if (n == 1) {
moveone(k, a, b);
moveone(k, b, c);
}
else {
hanoi(n - 1, a, b, c, k);
moveone(k, a, b);
hanoi(n - 1, c, b, a, k);
moveone(k, b, c);
hanoi(n - 1, a, b, c, k);
}
}

int main() {
int n, k;
while (cin >> n >> k&&n) {
for (int i = 1; i <= 3; i++) {
while (!p[i].empty())p[i].pop();
while (!ans[i].empty())ans[i].pop();
}
flag = false;
for (int i = n; i > 0; i--)
p[1].push(i);
hanoi(n, 1, 2, 3, k);
for (int i = 1; i <= 3; i++) {
if (ans[i].empty())
cout << 0;
else while (!ans[i].empty()) {
cout << ans[i].top()<<" ";
ans[i].pop();
}
cout << endl;
}
}
return 0;
}代码很复杂,肯定还有更简单的做法!先写这么多吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: