Uva 679 Dropping Balls (模拟/二叉树的编号)

题意:有一颗二叉树,深度为D,所有节点从上到下从左到右编号为1,2,3.....在结点一处放一个小球,每个节点是一个开关,初始全是关闭的,小球从顶点落下,小球每次经过开关就会把它的状态置反,现在问第k个球下落到D层时经过的开关编号

思路:lrj大哥的书上第一种方法是模拟,但是还是有要知道的知识点,对于一个结点k,其左子结点为2k,右结点为2k+1,它的父节点为k/2,深度为d的一颗树包含2^d个结点; 第二种方法,由于第一中方法模拟的运算量太大,所以我们lrj大哥说当I是奇数时,它是往左走的第(I+1)/2个小球,当I是偶数时,它是往右走第I/2个小球~

代码:

第一种:

#include <bits/stdc++.h>

using namespace std;
const int maxd=20;
int visit[1<<maxd];

int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        int go,k=(1<<n)-1;
        memset(visit,0,sizeof(visit));
        for(int i=0;i<m;i++)
        {
            go=1;
            for(;;)
            {
                if(visit[go]==0)
                {
                    visit[go]=1;
                    go=go*2;
                }
                else
                {
                    visit[go]=0;
                    go=go*2+1;
                }
                if(go>k) break;
            }
        }
        cout<<go/2<<endl;
    }
    return 0;
}

第二种:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

int main(int argc, char const *argv[])
{
  int D,I;
  while(cin>>D>>I){
     int k=1;
     for(int i=0;<D-1;i++){
         if(I%2){
         k=k*2;
         I=(I+1)/2;
         }
         else {
         k=k*2+1;
         I=I/2;
         }
     }
     cout<<k<<endl;
  }
  return 0;
}
原文地址:https://www.cnblogs.com/simplekinght/p/6628173.html