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 }