二叉樹-Dropping Balls(UVa 679)

在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

#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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章