码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 2966 In case of failure ->K_D树模版题

时间:2015-05-08 13:07:52      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:c   c++   acm   算法   数据结构   

分析:k_d树的模版题,参考了别人的写的;划分的时候采用坐标跨度作为分割依据的效率略比采用树的深度作为划分依据的高;nth_element函数比sort函数的效率高;全部采用getchar和putchar效率也能提高一些。

#include<iostream>
#include<algorithm>
using namespace std;

struct POINT
{
	int x,y;
};

struct K_D_Node
{
	POINT mid;              //分割中点
	int split_axis;         //分割的轴,0为x轴,1为y轴
	K_D_Node* child[2];     //0左子节点,1右子节点
};

#define N 100100
const __int64 inf=0x7fffffffffffffff;
POINT p[N],p2[N];
K_D_Node K_D_Tree[N];
int len;
__int64 ans;

bool cmpx(const POINT& a,const POINT& b)
{
	return a.x<b.x;
}

bool cmpy(const POINT& a,const POINT& b)
{
	return a.y<b.y;
}

K_D_Node* MallocNode()
{
	K_D_Tree[len].child[0]=K_D_Tree[len].child[1]=NULL;
	return &K_D_Tree[len++];
}

K_D_Node* Build_Tree(int L,int R,int depth)
{
	int mid,t;
	K_D_Node* q;
	int minx,miny,maxx,maxy;

	if(L>R) return NULL;
	q=MallocNode();

	//----------------------
	//t=depth%2;               //用树的深度作为分割依据
	//---------------------

	minx=min_element(p+L,p+R,cmpx)->x;          //用坐标跨度作为划分依据
	miny=min_element(p+L,p+R,cmpy)->y;
	maxx=max_element(p+L,p+R,cmpx)->x;
	maxy=max_element(p+L,p+R,cmpy)->y;

	if(maxx-minx>=maxy-miny)
		t=0;
	else
		t=1;

	q->split_axis=t;
	if(L==R)
	{
		q->mid=p[L];
		return q;
	}

	mid=(L+R)>>1;
	if(t==0)                   //以x轴分割
		nth_element(p+L,p+mid,p+R+1,cmpx);
	//	sort(p+L,p+R+1,cmpx);
	else
		nth_element(p+L,p+mid,p+R+1,cmpy);
	//	sort(p+L,p+R+1,cmpy);

	q->mid=p[mid];
	q->child[0]=Build_Tree(L,mid-1,depth+1);   //构建左子树
	q->child[1]=Build_Tree(mid+1,R,depth+1);
	return q;
}

__int64 DIS(const POINT& a,const POINT& b)
{
	__int64 xx,yy;

	xx=a.x-b.x;
	yy=a.y-b.y;
	return (__int64)xx*xx+(__int64)yy*yy;
}

void Query(K_D_Node* q,const POINT& a)
{
	int tmp,s;
	__int64 dis;     //距离平方

	if(q==NULL) return ;

	if(q->split_axis==0)     //X轴
	{
		tmp=q->mid.x;
		s=a.x;
	}
	else                     //Y轴
	{
		tmp=q->mid.y;
		s=a.y;
	}
	if(s<=tmp)
		Query(q->child[0],a);  //左子树
	else
		Query(q->child[1],a);

	dis=DIS(q->mid,a);
	if(dis && dis<ans)//注意这里必须要是dis不等于0才更新,避免处理到自身点,如果输入中有重复点则不能处理
		ans=dis;

	if((__int64)(tmp-s)*(tmp-s)<ans)  //可能在另一半中,查找另一半
	{
		if(s<=tmp)
			Query(q->child[1],a);
		else
			Query(q->child[0],a);
	}
}

int ReadInt()  
{  
    int ans;  
    char c;  
  
    c=getchar();  
    while(c<'0' || c>'9') c=getchar();  
  
    ans=c-'0';  
    while((c=getchar())>='0' && c<='9')  
    {  
        ans=ans*10+c-'0';  
    }  
    return ans;  
}

void PutInt64(__int64 x)  
{  
    int b[32],i;  
  
    i=0;  
    while(x)  
    {  
        b[i++]=x%10;  
        x/=10;  
    }  
    for(i--;i>=0;i--)  
        putchar(b[i]+'0');  
}

int main()
{
	int t,n,i;
	K_D_Node* root;

	t=ReadInt();
	while(t--)
	{
		n=ReadInt();
		for(i=0;i<n;i++)
		{
			p[i].x=ReadInt();
			p[i].y=ReadInt();
			p2[i]=p[i];
		}

		len=0;
		root=Build_Tree(0,n-1,0);   //建立k_d树
		for(i=0;i<n;i++)
		{
			ans=inf;
			Query(root,p2[i]);
			PutInt64(ans);
			putchar('\n');
		}
	}
    return 0;
}


HDU ACM 2966 In case of failure ->K_D树模版题

标签:c   c++   acm   算法   数据结构   

原文地址:http://blog.csdn.net/a809146548/article/details/45576907

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!