P1242 新汉诺塔

题目描述

设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号。将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A、B、C,这个状态称为初始状态。

现在要求找到一种步数最少的移动方案,使得从初始状态转变为目标状态。

移动时有如下要求:

·一次只能移一个盘;

·不允许把大盘移到小盘上面。

输入输出格式

输入格式:

文件第一行是状态中圆盘总数;

第二到第四行分别是初始状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号;

第五到第七行分别是目标状态中A、B、C柱上圆盘的个数和从上到下每个圆盘的编号。

输出格式:

每行一步移动方案,格式为:move I from P to Q

最后一行输出最少的步数。

输入输出样例

输入样例#1: 
5
3 3 2 1
2 5 4
0
1 2
3 5 4 3
1 1
输出样例#1: 
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 B
move 2 from C to A
move 1 from B to C
7

说明

圆盘总数≤45

每行的圆盘描述是从下到上的圆盘编号

Solution:

  最近太蠢了,打了个爆搜,爆$0$`~`。。。

  正解思路实在是巧妙,我们处理出每个盘的起始位置和目标位置,然后贪心的想到,我们应该从大到小让盘依次移到目标位置,移动过程中就是让小盘让路(即移到另一个中间盘上),然后每次就层层递归,输出就好了。(怎么会有这么巧的思路~)

代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 4 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 5 using namespace std;
 6 const int N=55;
 7 int n,fr[N],to[N],ans;
 8 string s="ABC";
 9 
10 il void dfs(int u,int v){
11     if(fr[u]==v)return;
12     Bor(i,1,u-1) dfs(i,6-fr[u]-v);
13     printf("move %d from %c to %c\n",u,s[fr[u]-1],s[v-1]);
14     fr[u]=v,ans++;
15 }
16 
17 int main(){
18     cin>>n;
19     int t,x;
20     For(i,1,3){
21         cin>>t;
22         while(t--)cin>>x,fr[x]=i;
23     }
24     For(i,1,3){
25         cin>>t;
26         while(t--)cin>>x,to[x]=i;
27     }
28     Bor(i,1,n) dfs(i,to[i]);
29     cout<<ans;
30     return 0;
31 }

猜你喜欢

转载自www.cnblogs.com/five20/p/9138583.html