zoukankan      html  css  js  c++  java
  • 分治法—hdu1007

     分治法吧,我也是第一次做题。就以我的理解对hdu1007来讲一下到目前为止我对分治法的理解吧。

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007

    题意:题意很清楚,就是求一个平面内的最近点对,然后输出最近点对距离的一半。

    思路:首先能想到的肯定是直接暴力。但是我们看这个数据10e5,直接暴力的话铁定超时,所以就不得不用分治了。。

    所谓分治就是先把对应点的x坐标排序,然后再分别求出两部分的最小的距离d1和d2,d=min(d1,d2),当然,当我们把x分为两部分时,然后再递归二分吧,每次到还剩两个数据时直接求出他们的距离。每次返回都和d取最小值。当然这样我们还没有计算不同区间的距离,这个比较重要,我们每次都把各个数据的x和d比较,>的话就肯定不行的了,然后记录<=的数据,另设数组保存。再判断y与d的关系,>的话,肯定也是不行的了。其实我的理解分治就是优化时间复杂度的吧,要是能暴力该有多好。

    ac代码:

    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #define INF 0x3f3f3f3f
    #define maxn 100010
    using namespace std;
    struct note
    {
        double x,y;
    };
    note p[maxn],t[maxn];
    int cmpxy(note a,note b)
    {
        if(a.x==b.x)
        return a.y<b.y;
        return a.x<b.x;
    }
    int cmpy(note a,note b)
    {
        return a.y<b.y;
    }
    double dis(note a,note b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));//计算两点间的距离 
    }
    
    double closet(int left,int right)
    {
        double d=INF;//赋初值为极大 
        if(left==right)
        return d;//一个点时,直接返回极大 
        if(left+1==right)//当分到只剩两个点时直接算出他们的距离 
        {
            return dis(p[left],p[right]);
        }
        int mid=(left+right)/2;//算中间值 
        double d1=closet(left,mid);
        double d2=closet(mid+1,right);//递归 
        d=min(d1,d2);//更新小值 
        int k=0;
        for(int i=left;i<=right;i++)
        {
            if(fabs(p[i].x-p[mid].x)<=d)//大于d的就不要了 
            t[k++]=p[i];
        }
        sort(t,t+k,cmpy);//以y的值由小到大排序 
        for(int i=0;i<k;i++)
        {
            for(int j=i+1;j<k&&t[j].y-t[i].y<d;j++)//大于d就不要了 
            {
                
                d=min(d,dis(t[i],t[j]));//更新d的值,直到找到最小 
            }
        }
        return d;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF&&n)
        {
            for(int i=0;i<n;i++)
            {
                scanf("%lf%lf",&p[i].x,&p[i].y);
            }
            sort(p,p+n,cmpxy);//排序,以x的坐标由小到大排序 
            printf("%.2lf
    ",closet(0,n-1)/2);//输出最小的值的一半 
            
        }
        return 0;
     } 

    你窥探过我最不安的手,在青春最寒冷的时候。

  • 相关阅读:
    贪心:SPOJ Backup Files
    杂题 SPOJ MOBILE2
    杂题 UVAoj 10000 Longest Paths
    杂题 UVAoj 107 The Cat in the Hat
    DP(斜率优化):HDU 3507 Print Article
    搜索(DLX): POJ 3074 3076 Sudoku
    DLX模板
    PHP代码优化技巧大盘点
    盘点PHP编程常见失误
    PHP Socket 编程详解
  • 原文地址:https://www.cnblogs.com/2000liuwei/p/10638587.html
Copyright © 2011-2022 走看看