题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4199

没想透为啥旋转卡壳跟枚举跑时间差不多。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) == ;
} ///向量(x,y)的极角用atan2(y,x);
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);
int T;
cin>>T;
while(T--){
cin>>n;
int cnt = ;
double x,y,w;
for(int i=;i<=n;i++){
scanf("%lf %lf %lf",&x,&y,&w);
P[cnt++] = Point(x,y);
P[cnt++] = Point(x+w,y);
P[cnt++] = Point(x,y+w);
P[cnt++] = Point(x+w,y+w);
}
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("%.lf\n",Maxlen);
}
return ;
}

旋转卡壳:

#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) == ;
} ///向量(x,y)的极角用atan2(y,x);
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);
int T;
cin>>T;
while(T--){
cin>>n;
int cnt = ;
double x,y,w;
for(int i=;i<=n;i++){
scanf("%lf %lf %lf",&x,&y,&w);
P[cnt++] = Point(x,y);
P[cnt++] = Point(x+w,y);
P[cnt++] = Point(x,y+w);
P[cnt++] = Point(x+w,y+w);
}
cnt = ConvexHull(P,cnt,Goal);
double Maxlen = RotatingCalipers(Goal,cnt);
printf("%.lf\n",Maxlen);
}
return ;
}

UVa1453或La4728 凸包+枚举(或旋转卡壳)的更多相关文章

  1. hdu 2187(凸包直径 1.枚举 2.旋转卡壳)

    Beauty Contest Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 33115   Accepted: 10278 ...

  2. [Bzoj1069][Scoi2007]最大土地面积(凸包)(旋转卡壳)

    1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 3629  Solved: 1432[Submit][Sta ...

  3. 【POJ 2187】Beauty Contest(凸包直径、旋转卡壳)

    给定点集的最远两点的距离. 先用graham求凸包.旋(xuán)转(zhuàn)卡(qiǎ)壳(ké)求凸包直径. ps:旋转卡壳算法的典型运用 http://blog.csdn.net/hanch ...

  4. [模板] 计算几何2: 自适应Simpson/凸包/半平面交/旋转卡壳/闵可夫斯基和

    一些基本的定义在这里: [模板] 计算几何1(基础): 点/向量/线/圆/多边形/其他运算 自适应Simpson Simpson's Rule: \[ \int ^b_a f(x)dx\approx ...

  5. BZOJ 1185 [HNOI2007]最小矩形覆盖:凸包 + 旋转卡壳

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 题意: 给出二维平面上的n个点,问你将所有点覆盖的最小矩形面积. 题解: 先找出凸 ...

  6. 【BZOJ 1069】【SCOI 2007】最大土地面积 凸包+旋转卡壳

    因为凸壳上对踵点的单调性所以旋转卡壳线性绕一圈就可以啦啦啦--- 先求凸包,然后旋转卡壳记录$sum1$和$sum2$,最后统计答案就可以了 #include<cmath> #includ ...

  7. UVA 4728 Squares(凸包+旋转卡壳)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17267 [思路] 凸包+旋转卡壳 求出凸包,用旋转卡壳算出凸包的直 ...

  8. 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖

    1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1945  Solve ...

  9. HDU 5251 矩形面积(二维凸包旋转卡壳最小矩形覆盖问题) --2015年百度之星程序设计大赛 - 初赛(1)

    题目链接   题意:给出n个矩形,求能覆盖所有矩形的最小的矩形的面积. 题解:对所有点求凸包,然后旋转卡壳,对没一条边求该边的最左最右和最上的三个点. 利用叉积面积求高,利用点积的性质求最左右点和长度 ...

随机推荐

  1. Android开发--二维码开发应用(转载!)

    android项目开发 二维码扫描   基于android平台的二维码扫描项目,可以查看结果并且链接网址 工具/原料 zxing eclipse 方法/步骤   首先需要用到google提供的zxin ...

  2. IOS-textField

    //初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 130, ...

  3. 【转】iOS25彩票 幸运转盘

    原文 : http://www.it165.net/pro/html/201409/21216.html 最终效果图: 各个view的关系图: 背景圆盘(需穴ky"http://www.it ...

  4. Objective-C 实例方法可见度,方法

    一 实例方法可见度,方法 1.实例变量的可见度 可见度                                                                       特点 ...

  5. 从零开始学java(猜数字游戏)

    练练手不喜勿喷,看到什么学习什么第一次发博客格式就见见谅.....                                            2016-07-21 19:55:02 imp ...

  6. 【BZOJ1146】【树链剖分+平衡树】网络管理Network

    Description M 公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 信网络.该网络的结构由N个 ...

  7. 第八篇、SVN在Mac上使用

    Mac自带svn软件 1.创建目录 svn-repository/source-code 2.svnadmin create /Users/liaokailin/svn-repository/sour ...

  8. linux常用指令(飞天云)

    1.svn相关指令 svn co svn://... //check out 到本地 2.pangu相关 pu cpdir pangu://...        //复制pangu里面对应的文件夹到本 ...

  9. 生成订单唯一id

    $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'); $orderSn = $yCode[intval(date('Y') ...

  10. python路径相关

    import sys import os sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 将当 ...