Dropping Balls UVA - 679 (二叉树 思维)

Dropping Balls UVA - 679 (二叉树 思维)




题意:

给出深度为D的儿二叉树, 所有叶子的深度都相同, 每一个节点有一个开关, 节点编号规则如图
在这里插入图片描述
在1处放一个小球, 如果该节点关闭往左走, 否则往右走, 每次经过节点改变节点开关状态, 求第I个小球从哪个节点出来

题解:

这道题的树比较稠密, 可以用数组来存, 比较容易想到的算法就是遍历I次, 模拟小球的下落, 最终看出口在哪, 如下代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 1<<20;

bool t[maxn]; //最大节点为2*20-1个
int I, D, T;
int drop(){
    //模拟小球下落的过程并返回最后所在叶子编号
    int cur = 1;
    while(cur <= (1<<(D-1)) -1){
        if(!t[cur*2])
            t[cur*2]^=1, cur = cur*2;
        else
            t[cur*2+1]^=1, cur = cur*2+1;
    }
    return cur;
}
int main()
{
    cin >> T;
    while(T--){
        cin >> D;
        if(D==-1) break;
        cin >> I;
        ms(t, 0);
        for(int i = 1; i <= I; i++){
            if(i==I) cout << drop() << endl;
            else drop();
        }
    }
	return 0;
}

上面的代码交上去会TLE, 因为时间复杂度过大了, 下面引用一下紫书的讲解.
从小球的行走过程中可以找到规律, 通过二叉树只有左右和奇偶性来判断的

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 1<<20;

int I, D, T;
int main()
{
    cin >> T;
    while(T--){
        cin >> D;
        if(D==-1) break;
        cin >> I;

        int k = 1;
        for(int i = 0; i < D-1; i++){
            if(I%2)
                k*=2, I = (I+1)/2;
            else
                k = k*2+1, I/=2;
        }
        cout << k << endl;
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a1097304791/article/details/88044649