• 2016 ICPC青岛站---k题 Finding Hotels(K-D树)


    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=5992

    Problem Description
    There are N hotels all over the world. Each hotel has a location and a price. M guests want to find a hotel with an acceptable price and a minimum distance from their locations. The distances are measured in Euclidean metric.
     
    Input
    The first line is the number of test cases. For each test case, the first line contains two integers N (N ≤ 200000) and M (M ≤ 20000). Each of the following N lines describes a hotel with 3 integers x (1 ≤ x ≤ N), y (1 ≤ y ≤ N) and c (1 ≤ c ≤ N), in which x and y are the coordinates of the hotel, c is its price. It is guaranteed that each of the N hotels has distinct x, distinct y, and distinct c. Then each of the following M lines describes the query of a guest with 3 integers x (1 ≤ x ≤ N), y (1 ≤ y ≤ N) and c (1 ≤ c ≤ N), in which x and y are the coordinates of the guest, c is the maximum acceptable price of the guest.
     
    Output
    For each guests query, output the hotel that the price is acceptable and is nearest to the guests location. If there are multiple hotels with acceptable prices and minimum distances, output the first one.
     
    Sample Input
    2
    3 3
    1 1 1
    3 2 3
    2 3 2
    2 2 1
    2 2 2
    2 2 3
    5 5
    1 4 4
    2 1 2
    4 5 3
    5 2 1
    3 3 5
    3 3 1
    3 3 2
    3 3 3
    3 3 4
    3 3 5
     
    Sample Output
    1 1 1
    2 3 2
    3 2 3
     
    5 2 1
    2 1 2
    2 1 2
    1 4 4
    3 3 5
     
    Source
     
     
    题意:有n个旅店(x,y,c),(x,y,c)表示旅店的平面坐标和住宿价格,现在有m个游客(x,y,c)想住宿,(x,y,c)表示游客的平面坐标和最高接受的价格,现在要求输出每一位游客选择的旅店(价格在小于游客接受的最高价格下的最近的旅店,如果有多个旅店符合要求,输出输入时排在前面的旅店);
     
    思路:K-D树,我在参加青岛现场赛时根本不知道这个算法,所以没做出来,最后铜牌了,有点可惜。这道题不难,是一道K-D树的模板题(如果不知道K-D树,想了解的话,看苟神的博客)。K-D树其实说到底是一棵二叉搜索树,但普通的二叉搜索树的节点是一维的,可以比较大小的向下搜索到叶子节点找到解,但K-D树的每个节点是多维的,在每个节点处有多维,这多维分量共同对结果产生影响,那么可以采用计算方差或者每一个分量轮流着来进行划分(我看网上大部分人都觉得使用每一个分量轮流来划分方法比较好,我以这种方法为例叙说),这样就不能绝对保证另一边的子树一定不包含解,但包含解的可能性要小于这边的子树,所以求解时优先搜索这边的子树,在回溯时判断另一边的子树是否需要搜索。从整体上看呢,感觉K-D树是一种暴力搜索+剪枝。
    唉,自己还是太弱,加油!
     
    代码如下:(另外这题,我写完用C++提交超时了,看了一下本题排名,发现所有过的代码都是G++提交的,我试着G++提交,过了。我不太明白这两种方式有什么不同,可有大神能说一下^_^)
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <set>
    #include <bitset>
    using namespace std;
    #define Sqrt2(x) (x)*(x)
    typedef long long LL;
    int N,M,idx;
    
    struct Node
    {
        int f[3];
        int id;
        bool operator<(const Node& s)const
        {
            return f[idx]<s.f[idx];
        }
    }data[200005],tr[4*200005];
    int flag[4*200005];
    pair<LL,Node> ans;
    
    void build(int l,int r,int i,int deep)
    {
        if(l>r) return;
        flag[i]=1;
        flag[i<<1]=0; flag[i<<1|1]=0;
        idx=deep%2;
        int mid=(l+r)>>1;
        nth_element(data+l,data+mid,data+r+1);
        tr[i]=data[mid];
        build(l,mid-1,i<<1,deep+1);
        build(mid+1,r,i<<1|1,deep+1);
    }
    
    void query(Node p,int i,int deep)
    {
        if(!flag[i]) return ;
        pair<LL,Node> c;
        c.second=tr[i];
        c.first=(LL)(Sqrt2((LL)p.f[0]-tr[i].f[0])+Sqrt2((LL)p.f[1]-tr[i].f[1]));
        bool fg=0;
        int idm=deep%2;
        int x=i<<1;
        int y=i<<1|1;
        if(p.f[idm]>=tr[i].f[idm]) swap(x,y);
        if(flag[x]) query(p,x,deep+1);
        if(ans.first==-1){
            if(c.second.f[2]<=p.f[2])
               ans.first=c.first,ans.second=c.second;
            fg=1;
        }
        else {
            if(c.second.f[2]<=p.f[2]&&(c.first<ans.first||(c.first==ans.first&&c.second.id<ans.second.id)))
                ans.first=c.first,ans.second=c.second;
            if((LL)(Sqrt2(tr[i].f[idm]-p.f[idm]))<ans.first)
                fg=1;
        }
        if(fg&&flag[y]) query(p,y,deep+1);
    }
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%d%d",&N,&M);
            for(int i=1;i<=N;i++)
            {
                for(int j=0;j<3;j++)
                 scanf("%d",&data[i].f[j]);
                data[i].id=i;
            }
            build(1,N,1,0);
            while(M--)
            {
                Node p;
                for(int i=0;i<3;i++)
                    scanf("%d",&p.f[i]);
                ans.first=-1;
                query(p,1,0);
                printf("%d %d %d
    ",ans.second.f[0],ans.second.f[1],ans.second.f[2]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    work_27_一次springBoot+orcal+Mabits PageHele的使用
    work_26_swagger2整合springBoot和使用
    work_25_docker--RabbitMq消息队列
    work_24_MYSQL从create table... 到分库分表
    work_23_常用的工具类
    work_22_MySQL分库分表的初识
    work_21_AtomicInteger API
    work_20_stream的使用
    MySQL 基础语句的练习2
    MySQL 基础语句的练习
  • 原文地址:https://www.cnblogs.com/chen9510/p/6082807.html
Copyright © 2020-2023  润新知