hdu 2184 汉诺塔移动

题意就不用我说了,接触汉诺塔的人都知道。。

说一下解题思路,若现在告诉你要移动m次,找到一个位置2^i-1<=m<2^i+1-1,那么此时就是说已经将n个盘子当中的i个盘子移动到了B盘和C盘上,但是到底是B盘还是C盘就要看具体情况了。。

若盘子数为3,那么就是要将前两个盘子移动到B盘,然后将最后一个盘子移动到C盘,此时你发现B盘最底层是不会出现基数盘。。

而C盘最底层绝对不会是偶数。。

若盘子数为偶数,则情况与上面相反。。。

仔细看看代码。。  应该可以找回ac最原始的快乐。。

View Code
 1   #include<iostream>
 2   using namespace std;
 3   int stack[3][64],head[3];
 4   void display()
 5   {
 6      for(int i=0;i<3;i++)
 7           {
 8              printf("%d",head[i]);
 9              for(int j=1;j<=head[i];j++)
10              {
11                 printf(" %d",stack[i][j]);
12              }        
13              printf("\n");
14           }     
15   }
16   int main()
17   {
18       __int64 n,m,dp[64];
19       for(int i=1;i<=63;i++)
20       {
21          dp[i]=1;
22          for(int j=0;j<i;j++)
23          dp[i]*=2;     
24          dp[i]--;   
25       }
26       int T;
27       scanf("%d",&T);
28       while(T--)
29       {
30           scanf("%I64d%I64d",&n,&m);
31           int sign=0;
32           if(n%2)sign=0;
33           else
34           sign=1;
35           int menu=0;
36           head[0]=head[1]=head[2]=0;
37           for(int j=n;j>=1;j--){head[menu]++;stack[menu][head[menu]]=j;}
38           while(m)
39           {
40              int i;
41              for(i=1;i<=63;i++)if(dp[i]>m){i--;break;}
42              m-=dp[i];
43              if(i>=n)
44              {
45                  for(int k=n;k>=1;k--)
46                  {
47                    head[menu]--;
48                    head[(menu+2)%3]++;
49                    stack[(menu+2)%3][head[(menu+2)%3]]=k;
50                  }
51                  break;
52              }
53              else
54              {
55                  if((i+sign)%2)
56                  {
57                       for(int k=i;k>=1;k--)
58                       {
59                            head[menu]--;
60                            head[(menu+2)%3]++;
61                            stack[(menu+2)%3][head[(menu+2)%3]]=k;      
62                       }
63                       if(m==0)break;
64                       m--;
65                       head[menu]--;
66                       head[(menu+1)%3]++;
67                       stack[(menu+1)%3][head[(menu+1)%3]]=i+1;
68                       menu=(menu+2)%3;
69                       n=i;
70                  }
71                  else
72                  {
73                       for(int k=i;k>=1;k--)
74                       {
75                            head[menu]--;
76                            head[(menu+1)%3]++;
77                            stack[(menu+1)%3][head[(menu+1)%3]]=k;      
78                       }
79                       if(m==0)break;
80                       m--;
81                       head[menu]--;
82                       head[(menu+2)%3]++;
83                       stack[(menu+2)%3][head[(menu+2)%3]]=i+1;
84                       menu=(menu+1)%3;
85                       n=i;
86                  }
87              }
88           }
89           display();
90       }
91       return 0;   
92   }

 

posted @ 2012-09-01 21:37  诺小J  阅读(210)  评论(0编辑  收藏  举报