博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
凸包模板
阅读量:4601 次
发布时间:2019-06-09

本文共 3226 字,大约阅读时间需要 10 分钟。

//下面是学长的模板;;

//题目就不讲了,赤裸裸的凸包。。
//注意:须先将n赋值,点数需大于二,求凸包的点的下标放在sta[]中,而不是凸包的点放在point[]中
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#define pi acos(-1.0)
using namespace std;

typedef double pointper;//点坐标的类型

#define POINTNUM 50005//最多点的个数

#define PREX 1e-11  //当点坐标为实数型的时候用
struct node
{
 pointper x,y;
}Point[10001];
class Polygon
{
public:
 int sta[POINTNUM];//在凸包上点的坐标
 node point[POINTNUM];
 bool flag[POINTNUM];
 int top,n,stab;//n为读入的点的个数,top-1为凸包上点的个数,(0~~top-2)是凸包上点的坐标,top-1和0存的都是第一个点;
 pointper x1,y1,x2,y2;
 polygon()
 {
  top=n=0;
 }
 static bool cmp(const node &A,const node &B)
 {
  return A.x<B.x||A.x==B.x&&A.y<B.y;//先根据X排序,然后根据Y排序
 }
 bool X(int x1,int y1,int x2,int y2,bool f)//f为true表示求的包括边上的点
 {
  if(f)
   return x1*y2-x2*y1>=0;
  return x1*y2-x2*y1>0;
 }
 bool X(double x1,double y1,double x2,double y2,bool f)//f为true表示求的包括边上的点
 {
  if(f)
   return x1*y2-x2*y1>=0.0||fabs(x1*y2-x2*y1)<PREX;
  return x1*y2-x2*y1>0.0;
 }
 void pointselect(bool f);//求凸包上的点,f为true表示求的包括边上的点;
 void getpoint(int i,bool f);
 void XY(int i);//辅助X()求叉乘
 double length();//求凸包的周长
 double area();//求凸包的面积;
 bool IsInPoly(int x,int y,bool f);
 bool IsInPoly(double x,double y,bool f);
};

Polygon Tubao;

void Polygon::XY(int i)

{
 x1=point[i].x-point[sta[top-2]].x;
 y1=point[i].y-point[sta[top-2]].y;
 x2=point[sta[top-1]].x-point[sta[top-2]].x;
 y2=point[sta[top-1]].y-point[sta[top-2]].y;
}

void Polygon::getpoint(int i,bool f)

{
 XY(i);
 if(top==stab||X(x1,y1,x2,y2,f))
 {
  sta[top++]=i;
  flag[i]=false;
 }
 else
 {
  top--;
  flag[sta[top]]=true;
  XY(i);
  while(top>stab&&!X(x1,y1,x2,y2,f))
  {
   top--;
   flag[sta[top]]=true;
   XY(i);
  }
  sta[top++]=i;
  flag[i]=false;
 }
}
void Polygon::pointselect(bool f)
{
 int i;
 memset(flag,true,n+1);
 sort(point,point+n,cmp);
 sta[0]=0;
 sta[1]=1;
 top=2;
 flag[1]=false;
 stab=1;
 for(i=2;i<n;i++)
  getpoint(i,f);
 stab=top;
 for(i=n-2;i>=0;i--)
  if(flag[i])
   getpoint(i,f);
}

double Polygon::length()

{
 double s=0.0;
 int i;
 for(i=1;i<top;i++)
  s+=sqrt(1.0*(point[sta[i]].x-point[sta[i-1]].x)*(point[sta[i]].x-point[sta[i-1]].x)+(point[sta[i]].y-point[sta[i-1]].y)*(point[sta[i]].y-point[sta[i-1]].y));
  return s;
}
double Polygon::area()
{
 double s=0.0;
 int i;
 for(i=1;i<top;i++)
  s+=point[sta[i-1]].x*point[sta[i]].y-point[sta[i]].x*point[sta[i-1]].y;
 return fabs(s/2);
}

bool Polygon::IsInPoly(int x,int y,bool f)//int型

{
 int i;
 for(i=1;i<top;i++)
  if(!X(x-point[sta[i-1]].x,y-point[sta[i-1]].y,(double)point[sta[i]].x-point[sta[i-1]].x,(double)point[sta[i]].y-point[sta[i-1]].y,f))
   return false;
  return true;
}

bool Polygon::IsInPoly(double x,double y,bool f)//double型

{
 int i;
 for(i=1;i<top;i++)
  if(!X(x-point[sta[i-1]].x,y-point[sta[i-1]].y,point[sta[i]].x-point[sta[i-1]].x,point[sta[i]].y-point[sta[i-1]].y,f))
   return false;
  return true;
}

int main()//HDU 1392 求周长

{
 while(scanf("%d",&Tubao.n)!=EOF&&Tubao.n)
 {

  for(int i=0;i<Tubao.n;i++)

  {
   scanf("%lf %lf",&Tubao.point[i].x,&Tubao.point[i].y);
  }
  if(Tubao.n==1)
  {
   printf("0.0\n");
   continue;
  }
  if(Tubao.n==2)
  {
   printf("%.2lf\n",sqrt((Tubao.point[1].x-Tubao.point[0].x)+(Tubao.point[1].y-Tubao.point[0].y)));
   continue;
  }
  Tubao.pointselect(1);
  printf("%.2lf\n",Tubao.length());
  printf("%.2lf\n",Tubao.area());
 }
 return 0;
}

转载于:https://www.cnblogs.com/Mu-Tou/archive/2011/08/10/2133885.html

你可能感兴趣的文章
你必知必会的SQL面试题
查看>>
html5 Canvas绘制时钟以及绘制运动的圆
查看>>
Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween
查看>>
JavaScript空判断
查看>>
洛谷 P1439 【模板】最长公共子序列(DP,LIS?)
查看>>
python timeit
查看>>
Wireless Network 并查集
查看>>
51nod 1019 逆序数
查看>>
20145202马超《JAVA》预备作业1
查看>>
云推送注意(MSDN链接)
查看>>
IDEA 生成 jar 包
查看>>
加减乘除混合版
查看>>
linux基础6-bash shell编程
查看>>
掌握这几种微服务模式助你成为更出色的工程师
查看>>
为什么很多语言选择在JVM上实现
查看>>
CSS Reset CSS Framework
查看>>
LeetCode算法扫题系列19
查看>>
nginx获取经过层层代理后的客户端真实IP(使用正则匹配)
查看>>
YII实现dropDownList 联动事件
查看>>
为什么JavaScript里面0.1+0.2 === 0.3是false
查看>>