#include <cstdio>
#include <cstring>
using namespace std;
const int maxD=20;
int b_tree[1<<maxD];//高度为D,节点最多2^D-1(1表示开,0表示关)
int main(){
int D,I,n;
scanf("%d",&n);
if(n!=-1){
for(int i=0;i<n;i++){
scanf("%d %d",&D,&I);
int num=(1<<D)-1;
int k;
memset(b_tree,0,sizeof(b_tree));//初始化开关(二叉树)
for(int j=0;j<I;j++){//处理I个小球
k=1;
int d=1;
while(d<D){
if(b_tree[k]){
b_tree[k]=0;
k=2*k+1;
}
else{
b_tree[k]=1;
k=2*k;
}
d++;
}
}
printf("%d\n",k);
}
}
return 0;
}
以上算法结果是正确的,但是运行会出现超时
的错误,此时查看他的时间复杂度,是O(n*I*D)
现在进行改进,发现:
对于树中每一结点,第一个到达它的球向左走,第二个到达它的球向右走,第三个到达它的球向左走…由此推出规律:
第奇数个到达结点的球向左(2k)走,第偶数个到达结点的球向右(2k+1)走.
I个球:如果I为奇数,那它是向左走的第(I+1)/2个球
如果I为偶数,那它是向右走的第I/2个球
#include <cstdio>
#include <cstring>
using namespace std;
const int maxD=20;
int b_tree[1<<maxD];//高度为D,节点最多2^D-1(1表示开,0表示关)
int main(){
int D,I,n;
scanf("%d",&n);
if(n!=-1){
for(int i=0;i<n;i++){
scanf("%d %d",&D,&I);
int num=(1<<D)-1;
int k;
memset(b_tree,0,sizeof(b_tree));//初始化开关(二叉树)
k=1;
int d=1;
while(d<D){
if(I%2){//奇数
k=2*k;
I=(I+1)/2;
}
else{//偶数
k=2*k+1;
I=I/2;
}
d++;
}
printf("%d\n",k);
}
}
return 0;
}