【题解】二维凸包

【题解】二维凸包

呵呵呵复习一下这个东西免得做到计算几何连暴力都不会嘤嘤嘤

免得到时候写斜率优化结果凸包不会了嘤嘤嘤

数学走起:
\[
\vec{a}=(x_1,y_1),\vec{b}=(x_2,y_2)
\shadow_{|\vec{a} \times\vec{b}|}=x_1y_2-x_2y_1
\]
根据右手螺旋定则。\(shadow\)是我乱搞的符号,虽然我搞不懂为什么是这样,但是这个应该和\(\sin(0.5\pi)=1,\sin0=0\)有关,就不纠结了,也比较好记。

遵循\(anson\)的意见,重载\(\%\)。

复杂度在排序\(O(n\log n)\)

搞个\(struct?\)套\(struct?\)玩玩。嘿嘿最近代码变sao了 有各种语法操作233(qaq)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
double stdx,stdy,ans;int n;

struct P{
#define pf(x) ((x)*(x))
      double x,y;
      struct vec{
        double x,y;
        vec(){x=y=0;}
        vec(const P&a,const P&b){x=b.x-a.x;y=b.y-a.y;}
        inline double operator %(const vec& a){return x*a.y-y*a.x;}
      };
      P(){x=y=0;}
      P(double a,double b){x=a;y=b;}
      inline void scan(){scanf("%lf%lf",&x,&y);}
      inline double operator -(P a){return sqrt(pf(x-a.x)+pf(y-a.y));}
      inline bool operator <(P a){
        double ret=vec(P(stdx,stdy),*this)%vec(P(stdx,stdy),a);
        if(ret>0) return 1;
        if(ret!=0) return 0;
        return *this-P(0,0)<a-P(0,0);
      }
#undef pf
}data[maxn];
vector < P > s;

int main(){
#ifndef ONLINE_JUDGE
      freopen("in.in","r",stdin);
      freopen("out.out","w",stdout);
#endif
      scanf("%d",&n);
      data[1].scan();stdx=data[1].x;stdy=data[1].y;
      for(register int t=2;t<=n;++t)
        if(data[t].scan(),data[t].y<stdy)
          stdy=data[t].y,stdx=data[t].x,swap(data[1],data[t]);
      sort(data+2,data+n+1);
      s.push_back(data[1]);
      for(register int t=2;t<=n;s.push_back(data[t]),++t)
        while(s.size()>1&&P::vec(*(s.end()-2),*(s.end()-1))%P::vec(*(s.end()-2),data[t])<0) s.pop_back();
      if(s.size()>2) s.push_back(*s.begin());
      for(register int t=1,edd=s.size();t< edd;++t)
        ans+=s[t]-s[t-1];
      return !printf("%.2lf\n",ans);
}

原文地址:https://www.cnblogs.com/winlere/p/10611894.html

时间: 2024-10-01 23:30:15

【题解】二维凸包的相关文章

UVA 10652 Board Wrapping(二维凸包)

传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组先输入木板个数n,接下来n行,每行x,y,w,h,j.(x,y)是木板中心的坐标,w是宽,h是高,j是顺时针旋转的角度. 木板互不相交. 输出:对于每组数据,输出木板总面积占包装总面积的百分比,保留小数点后1位. 题解:典型的二维凸包问题,理解并调用模板即可. #include <math.h>

计算几何 二维凸包问题 Andrew算法

凸包:把给定点包围在内部的.面积最小的凸多边形. Andrew算法是Graham算法的变种,速度更快稳定性也更好. 首先把所有点排序,按照第一关键字x第二关键字y从小到大排序,删除重复点后得到点序列P1...Pn. 1)把P1,P2放入凸包中,凸包中的点使用栈存储 2)从p3开始,当下一个点在凸包当前前进方向(即直线p1p2)左边的时候继续: 3)否则依次删除最近加入凸包的点,直到新点在左边. 如图,新点P18在当前前进方向P10P15的右边(使用叉积判断),因此需要从凸包上删除点P15和P10

使用Graham扫描法求二维凸包的一个程序

1 #include "includeall.h" 2 #include "Link.class.h" 3 4 int RightOrLeft(float x1,float y1,float x2,float y2,float x3,float y3)//判断第三个点在前两个点连成的直线的哪个位置,-1 左边,0,直线上,1 右边 5 { 6 float X=(y3-y1)*(x2-x1)/(y2-y1)+x1; 7 if(X<x3) 8 { 9 return

二维凸包模板

double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } double mul(Point p0,Point p1,Point p2) { return cross(p1-p0,p2-p0); } double dis(Point a) { return sqrt(a.x*a.x+a.y*a.y); } bool cmp(Point a,Point b) { if(dcmp(mul(p[0],a,b))==0) return dis(a-

二维凸包

二维凸包模板 p[1010]//输入的点集,res[1010]//输出的点集 int n;//点的个数 int cmp(Point a,Point b)//先对x坐标排序,在比较y坐标 { if(a.x==b.x) return a.y<b.y; return a.x<b.x; } int ConvexHull()//返回凸包顶点数 { sort(p,p+n,cmp); int m=0; for(int i=0;i<=n-1;i++) { while(m>1&&Cr

二维凸包的板子

二维凸包的板子 感觉没什么可说的,码风抄的孔老师的. #include <cstdio> #include <algorithm> #include <cmath> const int N=1e4+10; #define Point Vector const double eps=1e-8; bool cmp(double a,double b){return fabs(a-b)<eps;} struct Vector { double x,y; Vector()

Luogu 2742 二维凸包

Luogu 2742 二维凸包 使用 \(Andrew\) 算法.将点排序后分别求上下凸壳,用单调栈维护. 利用向量叉积来判断当前方向.若 \(v_1\times v_2<0\) ,说明 \(v_2\) 在 \(v_1\) 的右侧, \(<0\) 为左侧, \(=0\) 说明二者共线. 参考讲解. #include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #defin

HDU 5251 矩形面积(二维凸包旋转卡壳最小矩形覆盖问题) --2015百度之星题目

B - 矩形面积 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少. Input 第一行一个正整数 T,代表测试数据组数(),接下来 T 组测试数据. 每组测试数据占若干行,第一行一个正整数 ,代表矩形的数量.接下来 N 行,每行 8

算法模板——计算几何2(二维凸包——Andrew算法)

实现功能:求出二维平面内一对散点的凸包(详见Codevs 1298) 很神奇的算法——先将各个点按坐标排序,然后像我们所知的那样一路左转,求出半边的凸包,然后反过来求另一半的凸包 我以前正是因为总抱着想一步到位的想法,所以每次都跪得很惨(HansBug:事实上这次是我这辈子第一次A掉凸包题) 然后别的没了,就是凸包的基本思想 (顺便输出凸包周长C和面积S,好评如潮哦) 1 type arr=array[0..100005] of longint; 2 var 3 i,j,k,l,m,n,m1,m