poj 2187 凸包加旋转卡壳算法
题目链接:http://poj.org/problem?id=2187
旋转卡壳算法:http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html 或 http://cgm.cs.mcgill.ca/~orm/rotcal.frame.html
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = ;
const int maxe = ;
const int INF = 0x3f3f3f;
const double eps = 1e-;
const double PI = acos(-1.0); struct Point{
double x,y;
Point(double x=, double y=) : x(x),y(y){ } //构造函数
};
typedef Point Vector; 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);}
Vector operator / (Vector A , double p){return Vector(A.x/p,A.y/p);} bool operator < (const Point& a,const Point& b){
return a.x < b.x ||( a.x == b.x && a.y < b.y);
} int dcmp(double x){
if(fabs(x) < eps) return ;
else return x < ? - : ;
}
bool operator == (const Point& a, const Point& b){
return dcmp(a.x - b.x) == && dcmp(a.y - b.y) == ;
} double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y; }
double Length(Vector A) { return Dot(A,A); } //距离的平方;
double Angle(Vector A, Vector B) { return acos(Dot(A,B) / Length(A) / Length(B)); }
double Cross(Vector A, Vector B) { return A.x*B.y - A.y * B.x; } //凸包:
/**Andrew算法思路:首先按照先x后y从小到大排序(这个地方没有采用极角逆序排序,所以要进行两次扫描),删除重复的点后得到的序列p1,p2.....,然后把p1和p2放到凸包中。从p3开始,当新的
点在凸包“前进”方向的左边时继续,否则依次删除最近加入凸包的点,直到新点在左边;**/ //Goal[]数组模拟栈的使用;
int ConvexHull(Point* P,int n,Point* Goal){
sort(P,P+n);
int m = unique(P,P+n) - P; //对点进行去重;
int cnt = ;
for(int i=;i<m;i++){ //求下凸包;
while(cnt> && dcmp(Cross(Goal[cnt-]-Goal[cnt-],P[i]-Goal[cnt-])) <= ) cnt--;
Goal[cnt++] = P[i];
}
int temp = cnt;
for(int i=m-;i>=;i--){ //逆序求上凸包;
while(cnt>temp && dcmp(Cross(Goal[cnt-]-Goal[cnt-],P[i]-Goal[cnt-])) <= ) cnt--;
Goal[cnt++] = P[i];
}
if(cnt > ) cnt--; //减一为了去掉首尾重复的;
return cnt;
}
//旋转卡壳可以用于求凸包的直径、宽度,两个不相交凸包间的最大距离和最小距离
//计算凸包直径,输入凸包Goal,顶点个数为n,按逆时针排列,输出直径的平方
double RotatingCalipers(Point* Goal,int n){
double ret = ;
Goal[n]=Goal[]; //补上使凸包成环;
int pv = ;
for(int i=;i<n;i++){ //枚举边Goal[i]Goal[i+1],与最远顶点Goal[pv];利用叉积求面积的方法求最大直径;;
while(fabs(Cross(Goal[i+]-Goal[pv+],Goal[i]-Goal[pv+]))>fabs(Cross(Goal[i+]-Goal[pv],Goal[i]-Goal[pv])))
pv = (pv+)%n;
ret=max(ret,max(Length(Goal[i]-Goal[pv]),Length(Goal[i+]-Goal[pv+]))); //这个地方不太好理解,就是要考虑当pv与pv+1所在直线平行于i与i+1的情况;
}
return ret;
}
/*********************************分割线******************************/ Point P[maxn],Goal[maxn];
int n; int main()
{
//freopen("E:\\acm\\input.txt","r",stdin);
cin>>n;
int cnt = n;
for(int i=;i<n;i++){
double x,y;
scanf("%lf %lf",&x,&y);
P[i] = Point(x,y);
}
cnt = ConvexHull(P,cnt,Goal);
double Maxlen = RotatingCalipers(Goal,cnt);
printf("%.f\n",Maxlen);
return ;
}
直接枚举凸包的点也可以,n偏小;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = ;
const int maxe = ;
const int INF = 0x3f3f3f;
const double eps = 1e-;
const double PI = acos(-1.0); struct Point{
double x,y;
Point(double x=, double y=) : x(x),y(y){ } //构造函数
};
typedef Point Vector; 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);}
Vector operator / (Vector A , double p){return Vector(A.x/p,A.y/p);} bool operator < (const Point& a,const Point& b){
return a.x < b.x ||( a.x == b.x && a.y < b.y);
} int dcmp(double x){
if(fabs(x) < eps) return ;
else return x < ? - : ;
}
bool operator == (const Point& a, const Point& b){
return dcmp(a.x - b.x) == && dcmp(a.y - b.y) == ;
} double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y; }
double Length(Vector A) { return Dot(A,A); } //距离的平方;
double Angle(Vector A, Vector B) { return acos(Dot(A,B) / Length(A) / Length(B)); }
double Cross(Vector A, Vector B) { return A.x*B.y - A.y * B.x; } //凸包:
/**Andrew算法思路:首先按照先x后y从小到大排序(这个地方没有采用极角逆序排序,所以要进行两次扫描),删除重复的点后得到的序列p1,p2.....,然后把p1和p2放到凸包中。从p3开始,当新的
点在凸包“前进”方向的左边时继续,否则依次删除最近加入凸包的点,直到新点在左边;**/ //Goal[]数组模拟栈的使用;
int ConvexHull(Point* P,int n,Point* Goal){
sort(P,P+n);
int m = unique(P,P+n) - P; //对点进行去重;
int cnt = ;
for(int i=;i<m;i++){ //求下凸包;
while(cnt> && dcmp(Cross(Goal[cnt-]-Goal[cnt-],P[i]-Goal[cnt-])) <= ) cnt--;
Goal[cnt++] = P[i];
}
int temp = cnt;
for(int i=m-;i>=;i--){ //逆序求上凸包;
while(cnt>temp && dcmp(Cross(Goal[cnt-]-Goal[cnt-],P[i]-Goal[cnt-])) <= ) cnt--;
Goal[cnt++] = P[i];
}
if(cnt > ) cnt--; //减一为了去掉首尾重复的;
return cnt;
} /*********************************分割线******************************/ Point P[maxn],Goal[maxn];
int n; int main()
{
//freopen("E:\\acm\\input.txt","r",stdin);
cin>>n;
int cnt = n;
for(int i=;i<n;i++){
double x,y;
scanf("%lf %lf",&x,&y);
P[i] = Point(x,y);
}
cnt = ConvexHull(P,cnt,Goal);
double Maxlen = ;
for(int i=;i<cnt;i++)
for(int j=i+;j<cnt;j++){
Maxlen = max(Maxlen,Length(Goal[j]-Goal[i]));
}
printf("%.f\n",Maxlen);
return ;
}
poj 2187 凸包加旋转卡壳算法的更多相关文章
- POJ 2187 /// 凸包入门 旋转卡壳
题目大意: 求最远点对距离 求凸包上的最远点对 挑战263页 #include <cstdio> #include <string.h> #include <algori ...
- 算法复习——凸包加旋转卡壳(poj2187)
题目: Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest ...
- poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方
旋转卡壳求凸包的直径的平方 板子题 #include<cstdio> #include<vector> #include<cmath> #include<al ...
- poj 2187 Beauty Contest——旋转卡壳
题目:http://poj.org/problem?id=2187 学习材料:https://blog.csdn.net/wang_heng199/article/details/74477738 h ...
- poj 2187:Beauty Contest(旋转卡壳)
Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 32708 Accepted: 10156 Description Bes ...
- poj 2187 Beauty Contest —— 旋转卡壳
题目:http://poj.org/problem?id=2187 学习资料:https://blog.csdn.net/wang_heng199/article/details/74477738 h ...
- POJ 2187 Beauty Contest(凸包,旋转卡壳)
题面 Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the ...
- LA 4728 旋转卡壳算法求凸包的最大直径
#include<iostream> #include<cstdio> #include<cmath> #include<vector> #includ ...
- POJ2187 Beauty Contest (旋转卡壳算法 求直径)
POJ2187 旋转卡壳算法如图 证明:对于直径AB 必然有某一时刻 A和B同时被卡住 所以旋转卡壳卡住的点集中必然存在直径 而卡壳过程显然是O(n)的 故可在O(n)时间内求出直径 凸包具有良好的性 ...
随机推荐
- mac 下安装安卓模拟器
mac下的安卓模拟器——bluestacks 下载:http://pan.baidu.com/s/1kVvZyYz 该安卓模拟器除了能网络下载apk,本地还能安装apk,但是与win版不同,安装不是那 ...
- css-3列布局
三列布局的步骤是,先定义左右两侧,然后定义中间,并设置'中间'部分的'margin'属性.并且'中间'部分不用设置'width'.例如: <!DOCTYPE html PUBLIC " ...
- Const和ReadOnly
总结一下const和readonly有这么几条区别: const和readonly的值一旦初始化则都不再可以改写: const只能在声明时初始化:readonly既可以在声明时初始化也可以在构造器中初 ...
- 十二、C# 委托与Lambda表达式(匿名方法的另一种写法)
委托与Lambda表达式 1.委托概述 2.匿名方法 3.语句Lambda 4.表达式Lambda 5.表达式树 一.委托概述 相当于C++当中的方法指针,在C#中使用delegate 委托来 ...
- spl_autoload_register()和__autoload()
关于spl_autoload_register()和__autoload() 看两者的用法: //__autoload用法 function __autoload($classname) { ...
- Linux系统、版本、CPU、内存查看、硬盘空间
查看系统版本:lsb_release -a [root@localhost /]# lsb_release -a LSB Version: :core-4.0-amd64:core-4.0-no ...
- 我用Emacs,后来转向Vim——Vim学习之Vim键盘图(绝对值得珍藏)
Emacs本来就比较臃肿,麻烦.当我发现Vim键盘图时,我就渐渐转向Vim,追随Unix/Linux哲学去了.. 我用了Emacs三个月,因为它的学习曲线没Vim陡,这点吸引了,我使用Linux才7. ...
- JavaScript 获取当月天数
getDate() 方法可返回月份的某一天.取值范围是1~31 如果是0的话,就返回最后一天.这样就能取得当月的天数了 比如获取16年2月份的天数 var day = new Date(2016,2, ...
- .getBoundingClientRect()
.getBoundingClientRect() 该方法获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置,他返回的是一个对象,即Object,该对象有4个属性:top,left,right, ...
- phpcms v9用get-sql调用数据表中的图组图片示例代码
{pc:get sql="SELECT pictureurls FROM phpcms_picture_data where id = $id" start="0&quo ...