【ZCMU1158】松哥的二叉树(模拟)

题目链接

1158: 松哥的二叉树

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 54  Solved: 45
[Submit][Status][Web Board]

Description

有一棵满二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从上到下从左到右编号为1,2,3,…,2^D-1。松哥在结点1处放下一个小球,它会往下落。每个结点都会有一个开关,初始全为关闭,当每次有小球落到一个开关上时,开关的状态都会改变(开变关,关变开)。当小球到达某个结点时,如果该结点上的开关关闭,则小球往左走,否则往右走,直到走到叶子结点。现在有n个小球依次从结点1开始往下落,松哥想要知道第n个小球落在哪个结点,你能告诉他嘛?

Input

多组测试数据。每组测试数据包含两个整数D(D<=30),n(n<=2^D-1)。

Output

对于每组测试数据输出一个整数,代表最后一个小球最终下落在哪个结点。

Sample Input

4 1

4 2

4 3

Sample Output

8

12

10

【解题思路】

这题好像是道挺经典的题,我看紫书上也有,所以就写一下啦。

经过简单模拟可以发现如果下落的小球编号I是奇数,它是往左走的第(I+1)/2个小球,如果I是偶数,它是向右走的第I/2个小球。这样,可以直接模拟最后一个小球的路线。

这里简单说一下比如树有4层,求下落第7个球的位置。因为7是奇数,那么它是往左走的第4个小球到达2位置,此时,因为I是4是偶数,它是往右走的第2个小球,到达5位置,然后I是2是偶数,此时它是往右走的第1个小球,即最终到达11位置。

【代码】

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int d,n;
    while(~scanf("%d%d",&d,&n))
    {
        int k=1;
        for(int i=0;i<d-1;i++)
        {
            if(n%2)
            {
                k=k*2;
                n=(n+1)/2;
            }
            else
            {
                k=k*2+1;
                n=n/2;
            }
        }
        printf("%d\n",k);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39826163/article/details/81902146