zoukankan      html  css  js  c++  java
  • POJ 3714 Raid 近期对点题解

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/。未经本作者同意不得转载。

    https://blog.csdn.net/kenden23/article/details/36407517

    本题是一般近期对点求解。略微添加点限定:有两个集合点,要求不同集合中的点的近期对。

    那么就添加一个推断。假设是同一个集合中的点,那么就返回最大值。其它和一般的近期对点解法一样。

    注意:本题数据有重合点。那么就要防止分类的时候溢出。

    Geeks上的近期对的程序是无法处理有重合点的情况的。


    
    #include <stdio.h>
    #include <stdlib.h>
    #include <float.h>
    #include <math.h>
    #include <algorithm>
    #include <string.h>
    using std::sort;
    struct Point
    {
    	int x, y;
    	int whichSet;
    };
    
    inline int xCmp(const void *a, const void *b)
    {
    	const Point *a1 = static_cast<const Point *>(a);
    	const Point *b1 = static_cast<const Point *>(b);
    	return a1->x - b1->x;
    }
    
    inline int xCmp2(const Point &a, const Point &b)
    {
    	return a.x < b.x;
    }
    
    inline int yCmp2(const Point &a, const Point &b)
    {
    	return a.y < b.y;
    }
    
    inline int yCmp(const void *a, const void *b)
    {
    	const Point *a1 = static_cast<const Point *> (a);
    	const Point *b1 = static_cast<const Point *> (b);
    	return a1->y - b1->y;
    }
    
    inline float dist(Point &a, Point &b)
    {
    	if (a.whichSet == b.whichSet) return FLT_MAX;
    	float xd = (float)(a.x - b.x);
    	float yd = (float)(a.y - b.y);
    	return sqrtf(xd*xd + yd*yd);
    }
    
    float bruteForce(Point P[], int n)
    {
    	float m = FLT_MAX;
    	for (int i = 0; i < n; ++i)
    	{
    		for (int j = i+1; j < n; ++j)
    		{
    			float d = dist(P[i], P[j]);
    			if (d < m) m = d;
    		}
    	}
    	return m;
    }
    
    inline float mMin(float x, float y) { return x < y? x : y; }
    
    float stripClosest(Point strip[], int n, float d)
    {
    	for (int i = 0; i < n; i++)
    	{
    		for (int j = i+1; j < n && strip[j].y -strip[i].y < d; j++)
    		{
    			float t = dist(strip[i], strip[j]);
    			if (t < d) d = t;
    		}
    	}
    	return d;
    }
    
    float closestUtil(Point Px[], Point Py[], int n)
    {
    	if (n <= 3) return bruteForce(Px, n);
    
    	int m = n >> 1;
    	Point midPoint = Px[m];
    
    	Point *PyL = new Point[m+1];
    	Point *PyR = new Point[n-m-1];
    	int le = 0, ri = 0;
    	for (int i = 0; i < n; i++)
    	{//修正bug:添加le<m+1推断。防止反复点。引起溢出
    		if (Py[i].x <= midPoint.x && le < m+1) PyL[le++] = Py[i];
    		else PyR[ri++] = Py[i];
    	}
    
    	float dl = closestUtil(Px, PyL, le);//m+1);
    	float dr = closestUtil(Px+m+1, PyR, ri);//n-m-1);
    
    	float d = mMin(dl, dr);
    
    	Point *strip = new Point[n];
    	int j = 0;
    	for (int i = 0; i < n; i++)
    	{
    		if (fabsf(float(Py[i].x - midPoint.x)) < d) strip[j++] = Py[i];
    	}
    	d = mMin(d, stripClosest(strip, j, d));
    	delete [] strip;
    	delete [] PyL;
    	delete [] PyR;
    	return d;
    }
    
    float closest(Point P[], int n)
    {
    	Point *Px = new Point[n];
    	Point *Py = new Point[n];
    	memcpy(Px, P, n * sizeof(Point));
    	memcpy(Py, P, n * sizeof(Point));
    
    	//qsort(Px, n, sizeof(Point), xCmp);
    	sort(Px, Px+n, xCmp2);
    	//qsort(Py, n, sizeof(Point), yCmp);
    	sort(Py, Py+n, yCmp2);
    
    	float d = closestUtil(Px, Py, n);
    	delete [] Px;
    	delete [] Py;
    	return d;
    }
    
    int main()
    {
    	int T, n;
    	scanf("%d", &T);
    	while (T--)
    	{
    		scanf("%d", &n);
    		Point *P = new Point[n<<1];
    		for (int i = 0; i < n; i++)
    		{
    			scanf("%d %d", &P[i].x, &P[i].y);
    			P[i].whichSet = 1;
    		}
    		for (int i = n; i < (n<<1); i++)
    		{
    			scanf("%d %d", &P[i].x, &P[i].y);
    			P[i].whichSet = 2;
    		}
    		printf("%.3f
    ", closest(P, n<<1));
    		delete [] P;
    	}
    	return 0;
    }



  • 相关阅读:
    VB获取对象成员
    VB一键扫雷
    VBS代码
    C# LINQ GroupBy
    C# 元组和值元组
    数据结构笔记
    DoTween使用
    Unity中常用的数据结构总结
    Unity 坐标系转换
    .Net中C# Dictionary 用法
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10049988.html
Copyright © 2011-2022 走看看