poj2187题意
n个点 求最远点对的平方
思路
旋转卡壳模板
m==1 || m == 2的情况直接特判
逆时针枚举每一条线及当前线上两点(a[i],a[i+1])的可能对踵点(a[j]) 因为j对于i,i+1而言存在先单调增再单调减的过程,所以直接先前推进j(j = (j + 1) % m)
RotatingCalipers O(n) 凸包O(nlogn) 复杂度O(nlogn)
double RotatingCalipers(Point a[],int m){
if(m == 1) return 0.0;//一个点
if(m == 2) return dis(a[0],a[1]);
a[m] = a[0];
double res = 0.0;
int j = 2;//0~1这条线开始 从点2开始找对踵点
for(int i = 0;i < m; i++){//i∈[0,Top]
while(Cross(a[i + 1] - a[i],a[j] - a[i]) < Cross(a[i + 1] - a[i],a[j + 1] - a[i])) j = (j + 1) % m;
//单调性
res = max(res,max(dis(a[j],a[i]),dis(a[j],a[i + 1])));
}
return res;
}
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int MaxN = 5e4 + 5;
int n,Top;
struct Point{
double x,y;
Point(double x = 0,double y = 0):x(x),y(y){}
}p[MaxN],stack[MaxN],C;
typedef Point Vector;
int dcmp(double x){
if(fabs(x) < eps) return 0;
else return x < 0 ? -1:1;
}
Vector operator + (Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Vector A,Vector B){ return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double p){ return Vector(A.x*p,A.y*p);}
bool operator == (const Point &a,const Point &b){
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
double Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y;}
double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x;}
double dis(Point A,Point B){
return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y);
}
double compare(Point a,Point b,Point c){
return Cross(c - a,c - b);
}
bool cmp(Point a,Point b){
if(dcmp(compare(a,b,C)) == 0) return dis(a,C) < dis(b,C);
return dcmp(compare(a,b,C)) > 0;
}
void Graham_scan(Point p[]){
int i , k = 0;
Top = 2;
for(i = 1;i < n; i++){
if(p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x)) k = i;
}
swap(p[0],p[k]);
C = p[0];
sort(p + 1,p + n,cmp);
stack[0] = p[0];
stack[1] = p[1];
stack[2] = p[2];
for(int i = 3;i < n; i++){
while(Top > 1 && compare(p[i],stack[Top],stack[Top - 1]) >= 0) Top--;
stack[++Top] = p[i];
}
//[0,Top]
}
double RotatingCalipers(Point a[],int m){
if(m == 1) return 0.0;//一个点
if(m == 2) return dis(a[0],a[1]);
a[m] = a[0];
double res = 0.0;
int j = 2;//0~1这条线开始 从点2开始找对踵点
for(int i = 0;i < m; i++){//i∈[0,Top]
while(Cross(a[i + 1] - a[i],a[j] - a[i]) < Cross(a[i + 1] - a[i],a[j + 1] - a[i])) j = (j + 1) % m;
//单调性
res = max(res,max(dis(a[j],a[i]),dis(a[j],a[i + 1])));
}
return res;
}
int main()
{
scanf("%d",&n);
for(int i = 0; i < n; i++){
scanf("%lf %lf",&p[i].x,&p[i].y);
}
if(n == 2){
printf("%.0f\n",dis(p[0],p[1]));
return 0;
}
Graham_scan(p);
// for(int i = 0;i <= Top; i++){
// cout << i <<":" << stack[i].x << " " << stack[i].y<<endl;
// }
double ans = RotatingCalipers(stack,Top + 1);//Top + 1个点
printf("%.0f\n",ans);
return 0;
}
poj2079
O(n^2) 加一层枚举 确定两点 旋转找第三点 稍微改一下板子就好了
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int MaxN = 5e4 + 5;
int n,Top;
struct Point{
double x,y;
Point(double x = 0,double y = 0):x(x),y(y){}
}p[MaxN],stack[MaxN],C;
typedef Point Vector;
int dcmp(double x){
if(fabs(x) < eps) return 0;
else return x < 0 ? -1:1;
}
Vector operator + (Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Vector A,Vector B){ return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double p){ return Vector(A.x*p,A.y*p);}
bool operator == (const Point &a,const Point &b){
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
double Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y;}
double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x;}
double dis(Point A,Point B){
return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y);
}
double compare(Point a,Point b,Point c){
return Cross(c - a,c - b);
}
bool cmp(Point a,Point b){
if(dcmp(compare(a,b,C)) == 0) return dis(a,C) < dis(b,C);
return dcmp(compare(a,b,C)) > 0;
}
void Graham_scan(Point p[]){
int i , k = 0;
Top = 2;
for(i = 1;i < n; i++){
if(p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x)) k = i;
}
swap(p[0],p[k]);
C = p[0];
sort(p + 1,p + n,cmp);
stack[0] = p[0];
stack[1] = p[1];
stack[2] = p[2];
for(int i = 3;i < n; i++){
while(Top > 1 && compare(p[i],stack[Top],stack[Top - 1]) >= 0) Top--;
stack[++Top] = p[i];
}
//[0,Top]
}
double RotatingCalipers(Point a[],int m){
if(m == 1 || m == 2) return 0.0;//构不成三角形
a[m] = a[0];
double res = 0.0;
int j = 2;//0~1这条线开始 从点2开始找对踵点
for(int i = 0;i < m; i++){//i∈[0,Top]
j = (i + 2) % m;
for(int k = i + 1;k != i; k = (k + 1)%m){
while(fabs(Cross(a[k] - a[i],a[j] - a[i])) < fabs(Cross(a[k] - a[i],a[j + 1] - a[i]))) j = (j + 1) % m;
res = max(res,fabs(Cross(a[k] - a[i],a[j] - a[i])));
}
}
return res/2.0;
}
int main()
{
while(~scanf("%d",&n) && n != -1){
for(int i = 0; i < n; i++){
scanf("%lf %lf",&p[i].x,&p[i].y);
}
if(n == 2 || n == 1){
printf("0.00\n");
continue;
}
Graham_scan(p);
double ans = RotatingCalipers(stack,Top + 1);//Top + 1个点
printf("%.2f\n",ans);
}
return 0;
}