【递归与递推】新汉诺塔
2018-06-17 21:28:18来源:未知 阅读 ()
题目描述
现在要求找到一种步数最少的移动方案,使得从初始状态转变为目标状态。
移动时有如下要求:
·一次只能移一个盘;
·不允许把大盘移到小盘上面。
输入
第二到第四行分别是初始状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号;
第五到第七行分别是目标状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号。
输出
最后一行输出最少的步数。
样例输入
6
3 1 2 3
2 4 5
1 6
0
6 1 2 3 4 5 6
0
样例输出
move 4 from B to C move 1 from A to C move 2 from A to B move 1 from C to B move 3 from A to C move 1 from B to A move 2 from B to C move 1 from A to C move 5 from B to A move 1 from C to B move 2 from C to A move 1 from B to A move 3 from C to B move 1 from A to C move 2 from A to B move 1 from C to B move 4 from C to A move 1 from B to A move 2 from B to C move 1 from A to C move 3 from B to A move 1 from C to B move 2 from C to A move 1 from B to A move 6 from C to B move 1 from A to B move 2 from A to C move 1 from B to C move 3 from A to B move 1 from C to A move 2 from C to B move 1 from A to B move 4 from A to C move 1 from B to C move 2 from B to A move 1 from C to A move 3 from B to C move 1 from A to B move 2 from A to C move 1 from B to C move 5 from A to B move 1 from C to A move 2 from C to B move 1 from A to B move 3 from C to A move 1 from B to C move 2 from B to A move 1 from C to A move 4 from C to B move 1 from A to B move 2 from A to C move 1 from B to C move 3 from A to B move 1 from C to A move 2 from C to B move 1 from A to B 56
解:显然该题是用递归解题。因为不允许把大圆盘放在小圆盘上,所以,可以考虑为优先移动大圆盘。假设一共有n个圆盘,那么就应当优先移动编号为n的圆盘至目标位置。那么编号n的圆盘就不会对其他小圆盘有干扰了。接下来就是将编号为n-1的圆盘移动至其目标位置。
为了之后编写函数方便,输入时可进行加工。可将“初始状态”和“目标状态”分为两个数组a和b进行记录。a[i]即表示i号的初始位置,b[i]则为目标位置。先按照题目的输入顺序输入,一旦输入i,则在a[i]中记录
行数并转化为柱子的,b[i]同理。为了节省存储空间,可用一个变量重复输入。
如上述分析,从最大的n开始调用。函数需两个参数,即为需移动的圆盘编号k和要将其移动的位置t。若k的初始位置已在t上,可直接return。若没有,则先将k-1至1移动到辅助柱子上,这时就要用到循环并在循环
中递归。循环完后,再将a[k]改为t(相当于进行移动),并输出,再将移动次数加一。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 int n,cnt=0; //全局变量cnt计次 6 char a[46],b[46]; //记录圆盘的初始和目标位置 7 8 void move(int k,char t) 9 { 10 if(a[k]==t) 11 { 12 return; 13 } 14 char h; //辅助柱子 15 if((a[k]==65&&t==66)||(t==65&&a[k]==66)) 16 { 17 h=67; 18 } 19 if((a[k]==65&&t==67)||(t==65&&a[k]==67)) 20 { 21 h=66; 22 } 23 if((a[k]==67&&t==66)||(t==67&&a[k]==66)) 24 { 25 h=65; 26 } 27 for(int i=k-1;i>=1;i--) 28 { 29 move(i,h); //递归求k-1号圆盘的移动操作 30 } 31 printf("move %d from %c to %c\n",k,a[k],t); 32 a[k]=t; 33 cnt++; 34 } 35 36 int main() 37 { 38 cin>>n; 39 int m,t; 40 for(int i=1;i<=3;i++) 41 { 42 cin>>m; 43 for(int j=1;j<=m;j++) //记录每根柱子上的圆盘序号,并将圆盘的位置通过i转换的askll码表示 44 { 45 cin>>t; 46 a[t]=i+65-1; 47 } 48 } 49 for(int i=1;i<=3;i++) 50 { 51 cin>>m; 52 for(int j=1;j<=m;j++) 53 { 54 cin>>t; 55 b[t]=i+65-1; 56 } 57 } 58 for(int i=n;i>=1;i--) 59 { 60 move(i,b[i]); 61 } 62 cout<<cnt<<endl; 63 }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:1. Two Sum
- DSA_07:递归算法 2020-03-30
- 递归函数使用动态数组遇到的问题 2020-03-26
- 递归遍历树 2019-11-16
- RWMutex:共享/专有的递归互斥锁 2019-10-12
- 致初学者(四):HDU 2044~2050 递推专项习题解 2019-09-23
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash