hdu - 4347 - The Closest M Points - kd树

kd树为何物?不知。 先放着再说!!!

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int MAXN = 50010;
const int MAXK = 5;
const int MAXM = 10;

int n, m, k;
struct Point
{
    int p[MAXK];
    inline void input()
    {
        for(int i=0;i<k;++i)
        {
            scanf("%d", &p[i]);
        }
    }
    inline void output() const
    {
        for(int i=0;i<k;++i)
        {
            if(i)
            {
                printf(" ");
            }
            printf("%d", p[i]);
        }
        printf("\n");
    }
}point[MAXN], searchPoint;
int pointSet[16][MAXN];
int pointNumber[16];
set<Point> ans;

inline int getDistance(const Point &a, const Point &b)
{
    int ans = 0;
    for(int i=0;i<k;++i)
    {
        ans += (a.p[i] - b.p[i]) * (a.p[i] - b.p[i]);
    }
    return ans;
}

bool operator < (const Point &a, const Point &b)
{
    return getDistance(a, searchPoint) < getDistance(b, searchPoint);
}

struct TreeNode
{
    int dim, index;
    bool left, right;
}tree[MAXN];

int sortDimension;
bool compare(int x, int y)
{
    return point[x].p[sortDimension] < point[y].p[sortDimension];
}

bool buildTree(int x, int depth)
{
    int dim = depth % k;
    if(pointNumber[depth] == 0)
    {
        return false;
    }
    else if(pointNumber[depth] == 1)
    {
        tree[x].dim = dim;
        tree[x].index = pointSet[depth][0];
        tree[x].left = false;
        tree[x].right = false;
        return true;
    }
    sortDimension = dim;
    sort(pointSet[depth], pointSet[depth] + pointNumber[depth], compare);
    int mid = pointNumber[depth] >> 1;
    tree[x].dim = dim;
    tree[x].index = pointSet[depth][mid];
    pointNumber[depth + 1] = 0;
    for(int i=0;i<mid;++i)
    {
        pointSet[depth + 1][pointNumber[depth + 1] ++] = pointSet[depth][i];
    }
    tree[x].left = buildTree(x << 1, depth + 1);
    pointNumber[depth + 1] = 0;
    for(int i=mid+1;i<pointNumber[depth];++i)
    {
        pointSet[depth + 1][pointNumber[depth + 1] ++] = pointSet[depth][i];
    }
    tree[x].right = buildTree((x << 1) + 1, depth + 1);
    return true;
}

#ifndef ONLINE_JUDGE
void printTree(int x, int depth)
{
    printf("Layer %d: ", depth);
    point[tree[x].index].output();
    if(tree[x].left)
    {
        printTree(x << 1, depth + 1);
    }
    if(tree[x].right)
    {
        printTree((x << 1) + 1, depth + 1);
    }
}
#endif

inline void insertPossibility(const Point &point)
{
    ans.insert(point);
    if(ans.size() > m)
    {
        set<Point>::reverse_iterator it = ans.rbegin();
        ans.erase(*it);
    }
}

void queryTree(int x)
{
    insertPossibility(point[tree[x].index]);
    if(!tree[x].left && !tree[x].right)
    {
        return;
    }
    bool flag = false;
    int dist1 = searchPoint.p[tree[x].dim] - point[tree[x].index].p[tree[x].dim];
    dist1 *= dist1;
    if(searchPoint.p[tree[x].dim] < point[tree[x].index].p[tree[x].dim])
    {
        if(tree[x].left)
        {
            queryTree(x << 1);
        }
        if(tree[x].right)
        {
            if(ans.size() < m)
            {
                flag = true;
            }
            else
            {
                set<Point>::reverse_iterator it = ans.rbegin();
                Point temp = *it;
                int dist2 = getDistance(temp, searchPoint);
                if(dist1 <= dist2)
                {
                    flag = true;
                }
            }
            if(flag)
            {
                queryTree((x << 1) + 1);
            }
        }
    }
    else
    {
        if(tree[x].right)
        {
            queryTree((x << 1) + 1);
        }
        if(tree[x].left)
        {
            if(ans.size() < m)
            {
                flag = true;
            }
            else
            {
                set<Point>::reverse_iterator it = ans.rbegin();
                Point temp = *it;
                int dist2 = getDistance(temp, searchPoint);
                if(dist1 <= dist2)
                {
                    flag = true;
                }
            }
            if(flag)
            {
                queryTree(x << 1);
            }
        }
    }
}

void solve()
{
    ans.clear();
    queryTree(1);
}

int main()
{
    int t;
    while(~scanf("%d%d",&n,&k))
    {
        pointNumber[0] = n;
        for(int i=0;i<n;++i)
        {
            point[i].input();
            pointSet[0][i] = i;
        }
        buildTree(1, 0);
        #ifndef ONLINE_JUDGE
            printTree(1, 0);
        #endif
        scanf("%d", &t);
        while(t--)
        {
            searchPoint.input();
            scanf("%d", &m);
            solve();
            printf("the closest %d points are:\n", m);
            for(set<Point>::iterator it=ans.begin();it!=ans.end();++it)
            {
                it->output();
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值