最短距离的两点

给出一些整数对,它们表示平面上的点,求所有这些点中距离最近的两个点。

输入格式:

测试数据有多组。对于每组测试,先输入一个整数N,表示点的个数,再输入N个点(以两个整数表示横纵坐标)。若N为0,则表示输入结束。

输出格式:

对于每组测试,输入所有点中距离最短的两点,格式为“(a,b) (c,d)”,其中,a,b,c,d分别表示第一、二个点的横纵坐标。若有多个点对之间距离最短,以先输入者优先(如第一组样例所示)。

输入样例:

4
1 1
2 2
0 0
3 3
4
1 2
0 0
3 6
7 2
10
28 185
246 115
252 141
239 129
123 10
186 60
6 70
255 92
95 143
63 144
20
100 156
172 181
119 239
113 10
86 115
104 83
297 210
122 228
167 64
210 280
159 80
230 97
286 275
263 174
10 244
125 286
53 112
16 186
141 116
124 282
0

输出样例:

(1,1) (2,2)
(1,2) (0,0)
(246,115) (239,129)
(125,286) (124,282)

出处:

ZJUTOJ

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include <stdio.h>
#include <math.h>
void print_min_point(int a[],int b[],int N)
{
    float len(int a,int b,int c,int d);
    float min;
    min=len(a[0],b[0],a[1],b[1]);
    for(int i=0;i<N;i++)
        for(int j=i+1;j<N;j++)
            if(len(a[i],b[i],a[j],b[j])<min)
                min=len(a[i],b[i],a[j],b[j]);
    for(int i=0;i<N;i++)
    {
        int j=i+1;
        for(;j<N;j++)
        {
            if(len(a[i],b[i],a[j],b[j])==min)
            {
                printf("(%d,%d) (%d,%d)\n",a[i],b[i],a[j],b[j]);
                break;
            }

        }
        if(len(a[i],b[i],a[j],b[j])==min)
            break;
    }
}
float len(int a,int b,int c,int d)
{
    float value;
    value=sqrt((a-c)*(a-c)+(b-d)*(b-d));
    return value;
}
int main()
{
    int N;
    while(1)
    {
        scanf("%d",&N);
        if(N==0)
            break;
        int a[8600],b[8600];
        for(int i=0;i<N;i++)
            scanf("%d%d",&a[i],&b[i]);
        print_min_point(a,b,N);
    }
    return 0;
}

 

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 这是一个最近对问题,可以使用分治算法来解决。具体步骤如下: 1. 将所有按照横坐标排序,如果横坐标相同,则按照纵坐标排序。 2. 将集分成左右两个子集,分别递归最近对。 3. 计算左右两个子集中最近对的距离d。 4. 在所有横坐标距离小于d的中,计算纵坐标距离小于d的对的距离,更新最近对的距离。 5. 返回最近对的距离。 时间复杂度为O(nlogn)。 需要注意的是,在计算纵坐标距离小于d的对的距离时,可以使用滑动窗口的方法,将时间复杂度优化到O(n)。 ### 回答2: 对于给出整数对,每个整数表示平面上的一个,现在需要出所有中距离最近两个。 要解决这个问题,可以使用暴力算法和分治算法。 暴力算法是最简单的解决方法,它的思路是枚举平面上的每一对,计算它们之间的距离,最后找出最小的距离。但是这种方法的时间复杂度为O(n^2),当的数量很大时,效率很低。 分治算法是一种优化的方法。它的思路是将所有按横坐标排序,然后将平面分成左右两个部分。接着递归处理左右两个部分,找出左右两个部分中距离最近对,然后再找出跨越左右两个部分的最小对。最后取出三者中距离最小的对即可。这种算法的时间复杂度为O(nlogn)。 在编写代码时,可以使用Python编程语言来实现。代码如下: ``` import math def distance(point1, point2): """ 计算两个之间的距离 """ return math.sqrt((point1[0]-point2[0])**2+(point1[1]-point2[1])**2) def findClosestPair(points): """ 查找最近对 """ n = len(points) if n <= 1: return None, None, float('inf') elif n == 2: return points[0], points[1], distance(points[0], points[1]) # 按横坐标排序 points.sort(key=lambda x: x[0]) # 递归处理左右两个部分 mid = n//2 left_points = points[:mid] right_points = points[mid:] left_min_pair = findClosestPair(left_points) right_min_pair = findClosestPair(right_points) min_pair = left_min_pair if right_min_pair[2] < left_min_pair[2]: min_pair = right_min_pair # 计算跨越左右两个部分的最小对 x_bar = points[mid][0] strip_points = [point for point in points if abs(point[0]-x_bar)<min_pair[2]] strip_points.sort(key=lambda x: x[1]) strip_size = len(strip_points) for i in range(strip_size): for j in range(i+1, min(i+8, strip_size)): if distance(strip_points[i], strip_points[j]) < min_pair[2]: min_pair = strip_points[i], strip_points[j], distance(strip_points[i], strip_points[j]) return min_pair if __name__ == '__main__': # 示例集 points = [(0, 0), (1, 2), (4, 5), (3, 1), (2, 4), (7, 8)] print("集:", points) closest_pair = findClosestPair(points) print("最近对:", closest_pair) ``` 该代码可以输出集和最近对,例如: ``` 集: [(0, 0), (1, 2), (4, 5), (3, 1), (2, 4), (7, 8)] 最近对: ((2, 4), (3, 1), 3.1622776601683795) ``` 其中,第一行输出输入集,第二行输出最近对,最后一个数是这两个之间的距离。 ### 回答3: 我们假设有n个,将它们按照x坐标从小到大排序。接下来,我们通过分治算法来出距离最近两个。 首先,我们将所有的平均分成两个部分,分别处理左边的和右边的。我们递归地出左边部分和右边部分的最小距离。 接着,我们需要找到左边部分和右边部分之间的距离最小的两个。我们假设左边部分的最小距离为d1,右边部分的最小距离为d2,那么这两个距离中较小的那个就是整个平面的最小距离。接下来,我们需要考虑在“中间带”中是否存在距离更小的两个。 我们将所有x坐标在中间带内的按照y坐标从小到大排序,然后用一个指针i指向左边部分的最后一个。接着,我们逐个遍历中间带内的,对于每个,我们计算它和i所指向的之间的距离,如果这个距离比之前的最小距离还小,那么就更新最小距离。 最后,我们将左边部分和右边部分中的最小距离和中间带中的最小距离相比较,取最小值即可。 时间复杂度为O(nlogn)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮央乜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值