#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;
}