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++:
这个步骤和上面的不太一样,但原理基本相同。基本步骤就是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;
}代码很复杂,肯定还有更简单的做法!先写这么多吧!
一个最经典的便可举一反三,以往在比赛中遇到的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;
}代码很复杂,肯定还有更简单的做法!先写这么多吧!
相关文章推荐
- 关于C语言基本元素的相关问题自己的理解
- 关于openCV中的鸟瞰图例程原理的解释,相关问题的解答
- XMind Cloud相关问题解答
- 轻松理解Javascript变量的相关问题
- 字符编码问题-自己的理解
- eXtremeDB相关问题解答(3)
- 关于Xerces-C++执行schema校验相关问题的详细解答
- 关于CSDN博客文章个数不更新的相关问题解答
- SDN论坛看到BW的问题及相关解答(摘抄)
- vmware的vmnet-理解全景后解答两个问题
- Android 与gradle常见相关问题及解答(1)
- opencv相关问题理解(4)直方图操作!!
- 关于编码问题,自己的一些理解
- 企业对于搜索引擎优化的一些常见问题以及相关的解答
- DM9000相关问题解答
- 说说我对iAD的错误理解及一些相关问题
- vmware的vmnet-理解全景后解答两个问题
- 问题解答理解802.11n
- IP的相关问题解答
- 关于typeAliases标签理解 自己挖的坑啊,解决了好久的问题。