编程之美-2.11 扩展 寻找距离最远的两个点

一、问题描述

平面上有n个点,如何寻找距离最远的两个点?

二、解题思路

第一步,寻找凸包(因为最远距离的两个点一定在凸包上)

第二步,用旋转卡(qia)壳 寻找距离最大的点

凸包和旋转卡壳算法参见http://blog.csdn.net/kaytowin/article/details/5140111

三、代码实现


#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<stack>
#define INF 100000000
using namespace std;

struct point{
int x;
int y;
point(int x1,int y1):x(x1),y(y1){}
point(){}
};
struct maxLS{
point p1;
point p2;
int dist;
maxLS(point pp1,point pp2,int dist1):p1(pp1),p2(pp2),dist(dist1){}
maxLS(){}
};
int xmult(point p1,point p2,point p0){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
point p0(INF,INF);
vector<point> points;
vector<point> pstack;
void sort(vector<point>& points1){
for(int j=points.size()-1;j>=1;j--){
for(int i=1;i<j;i++){
int xm=xmult(points[i],points[i+1],p0);

if(xm<0){
point tmp=points[i];
points[i]=points[i+1];
points[i+1]=tmp;
}
}
}
}
void printPoints(vector<point> ps){
for(int i=0;i<ps.size();i++){
cout<<"<"<<ps[i].x<<","<<ps[i].y<<">"<<endl;
}
}
void convexHull(){
cout<<"打印输入点集:"<<endl;
printPoints(points);
sort(points);
cout<<"打印按极角排序的点集:"<<endl;
printPoints(points);
pstack.push_back(points[0]);
pstack.push_back(points[1]);
int stack_top=pstack.size()-1;
for(int i=2;i<points.size();i++){
stack_top=pstack.size()-1;
point pt2=pstack[stack_top];
point pt1=pstack[stack_top-1];
point ptcur=points[i];
int xm=(pt2.x-pt1.x)*(ptcur.y-pt2.y)-(ptcur.x-pt2.x)*(pt2.y-pt1.y);
while(xm<0){

pstack.pop_back();
stack_top=pstack.size()-1;
pt2=pstack[stack_top];
pt1=pstack[stack_top-1];
xm=(pt2.x-pt1.x)*(ptcur.y-pt2.y)-(ptcur.x-pt2.x)*(pt2.y-pt1.y);

}
pstack.push_back(points[i]);
}
cout<<"打印凸包点集:"<<endl;
printPoints(pstack);
}
int dist(point p1,point p2){
return (p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y);
}
maxLS rotatingCalipers(){
int q=1;
int maxLength=0;
maxLS mls;
for(int i=0;i<pstack.size()-1;i++){
while(xmult(pstack[i+1],pstack[(q+1)%pstack.size()],pstack[i])>xmult(pstack[i+1],pstack[q],pstack[i])){
q=(q+1)%pstack.size();
}
int d1=dist(pstack[i],pstack[q]);
int d2=dist(pstack[i+1],pstack[q]);
if(d1>d2){
maxLength=d1;
mls=maxLS(pstack[i],pstack[q],d1);

}else{
maxLength=d2;
mls=maxLS(pstack[i+1],pstack[q],d2);
}

}
return mls;
}
int main(){
cout<<"请输入节点数:"<<endl;
int n;
cin>>n;
cout<<"请输入"<<n<<"个节点:"<<endl;
int p0i=0;
int t=0;
while(n--){
int x;
int y;
cin>>x>>y;
if(y<p0.y||(y==p0.y&&x<p0.x)){
p0.x=x;
p0.y=y;
p0i=t;

}
t++;
points.push_back(point(x,y));
}
point tmp=points[0];
points[0]=points[p0i];
points[p0i]=tmp;

convexHull();
maxLS maxL= rotatingCalipers();
cout<<"两点最大距离:"<<maxL.dist<<endl;
cout<<"两点分别是:"<<"<"<<maxL.p1.x<<","<<maxL.p1.y<<">,";
cout<<"<"<<maxL.p2.x<<","<<maxL.p2.y<<">"<<endl;
system("pause");
return 0;
}

四、输入:

9

3 1
4 3
5 2
3 5
6 5
8 4
5 7
2 6
1 4

五、输出:

编程之美-2.11 扩展 寻找距离最远的两个点,布布扣,bubuko.com

时间: 2024-07-28 13:48:11

编程之美-2.11 扩展 寻找距离最远的两个点的相关文章

编程之美 2.10 扩展问题

编程之美 2.10 扩展问题 题目如下: 如果需要找出N个数组中的第二大数,需要比较多少次呢?是否可以使用过类似的分治思想来降低比较的次数呢? 解法一 我们最容易想到的方法就是:我们数组进行排序,取倒数第二个数即为所求.但是比较次数是很高的,不可取. 解法二 用2个中间变量来保存最大值和第二大的值,遍历一次数组即可得到最大值和第二大的值.比较次数为:2*N 实现代码如下: package com.wrh.firstpro; import java.util.Arrays; /* * 寻找数组中的

编程之美之2.5 寻找最大的K个数

[题目] 有很多无序的数,从中找出最大的K个数.假定他们都不相等. [解法一] 如果数据不是很多,例如在几千个左右,我们可以排一下序,从中找出最大的K个数.排序可以选择快速排序或者堆排序 [cpp] view plaincopy #include<stdio.h> #include<stdlib.h> int cmp(const void *a,const void *b){ return *(int *)a - *(int *)b; } int main(){ int n,k;

求子数组之和的最大值——编程之美 2.14 扩展问题 正确实现

使用动态规划求最大子数字和: s[i]表示data[i~n-1]以元素i开始的最大子数组和,a[i]表示data[i~n-1]中的最大子数组和 : s[i]=max(s[i+1]+data[i], data[i]); a[i]=max(a[i+1], s[i]); 由于数组s,a递推的时候,都只用到数组的前一个变量,所以可以用滚动数组节省空间. 扩展问题: 1) 如果数组首尾相连,即允许找到一组数字(A[i],···,A[n-1], A[0],···, A[j]),请使其和最大,怎么办?(书中答

【编程之美】2.5 寻找最大的k个数

有若干个互不相等的无序的数,怎么选出其中最大的k个数. 我自己的方案:因为学过找第k大数的O(N)算法,所以第一反应就是找第K大的数.然后把所有大于等于第k大的数取出来. 写这个知道算法的代码都花了2个多小时,反思,太慢了. 注意边界条件,不要混混沌沌的. /************我自己的解法*****************/ //选择数组a[N]中最大的第k个数 int Select(int * a, int N, int k) { if(k > N || a == NULL) { cou

《编程之美》3.6判断链表是否相交之扩展:链表找环方法证明

先看看原题:<编程之美>3.6编程判断两个链表是否相交,原题假设两个链表不带环. 为了防止剧透使得没看过原题目的读者丧失思考的乐趣,我把最好的解法隐藏起来.由于这个问题本身的解答并不是本文的重点,扩展问题也采用这种形式呈现. 注:位于(*)符号之间的文字出自于:http://blog.csdn.net/v_july_v/article/details/6447013,作者v_JULY_v. 用指针p1.p2分别指向两个链表头,不断后移:最后到达各自表尾时,若p1==p2,那么两个链表必相交 用

编程之美之寻找最大的k个数

这个题目很常见,方法也很多,这里总结了编程之美给出的几个比较好的方法,也算是对这个问题的一个总结. 方法一.partition算法,每次partition的复杂度为O(n),总的平均时间复杂度为O(nlogn) 分析:运用partition算法,如果返回的provit > k-1,则说明要找的数都在前面,把end= provit-1;如果provit < k-1,表明找到一部分,先把部分数据保存,然后start = provit + 1;如果正好相等,则保存后结束,具体代码如下: int pa

编程之美之子数组之和的最大值以及扩展(可首尾相连)

情形一:不允许首尾相连 此情况很常见,方法是动态规划,编程之美的方法三给出了解法,这里就直接给出代码了 int maxSubSum(vector<int>& data) { int length = data.size(); assert(length >= 0); int maxSum = data[length-1],startSum = data[length-1],begin = length-1,i; for(i = length-2;i >= 0;i--) {

&lt;&lt;编程之美&gt;&gt; -- 队列中取最大值操作的问题

不得不说编程之美是一本好书,虽然很多题目在做acm中的过程中遇到过,不过还是有很多值得思考的地方 这是今天在编程之美上看到的一个问题,对于栈转化成队列的一个思考 平时都太过依赖c++内函数库中的栈和队列,但是对于他们的扩展我们还是应该自己进行手写栈和队列来实现更简单的算法 题目大意: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v) : 将 v 加入队列 2. DeQueue: 使队列中队首元素删除并返回此元素 3.MaxElement: 返回队列中的最大元素 设计一种数据结构和算

编程之美之实时排名算法

首先来看一个实时排名算法 参考文献 某海量用户网站,用户拥有积分,积分可能会在使用过程中随时更新.现在要为该网站设计一种算法,在每次用户登录时显示其当前积分排名.用户最大规模为2亿:积分为非负整数,且小于100万. 存储结构 首先,我们用一张用户积分表user_score来保存用户的积分信息. 表结构: 示例数据: 下面的算法会基于这个基本的表结构来进行. 算法1:简单SQL查询 首先,我们很容易想到用一条简单的SQL语句查询出积分大于该用户积分的用户数量: select 1 + count(t