[USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包
二维凸包
假设平面上有
形象地来说,就是在这
下面,结合模板题,将会讲解求二维凸包的一种常用做法。
[USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包
题目背景
upd: 新增一组 hack 数据。
题目描述
农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。
输入格式
输入数据的第一行是一个整数。表示农夫约翰想要围住的放牧点的数目
第
输出格式
输出输出一行一个四舍五入保留两位小数的实数,代表围栏的长度。
样例 #1
样例输入 #1
4
4 8
4 12
5 9.3
7 8
样例输出 #1
12.00
提示
数据规模与约定
对于
Solution
求凸包的算法很多,这里只介绍一种:Graham 算法。这种算法的时间复杂度为
Graham 算法首先将会取出一个
按照排序后的顺序逐个将点加入一个栈中,这个栈存储了目前凸包上所有的点。
加入一个点的时候,先判断当前点加入栈顶后会不会将凸包变成凹包,换句话说,凸包上的点应该满足每两个点之间应该是向左转而非向右转。也就是说将当前点与栈顶的点组成一个向量
这样这个算法流程就很清晰了,可以结合代码理解:
Code
为了方便,我将栈封装了一个结构体,支持 push()
、pop()
、size()
、empty()
这些 STL
栈有的操作,并且重载了 []
运算符,使得可以访问栈中的任意元素,栈顶则是 s[1]
,栈顶的第二个元素是 s[2]
。
因为点和向量的表示方法是一致的,所以就使用了同一个结构体,并且重载了 *
和 -
运算,表示向量叉乘和向量减。
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
const int _SIZE=1e5;
struct VEC{
double x,y;
double operator* (const VEC &a) const {return x*a.y-a.x*y;}
VEC operator- (const VEC &a) const {return (VEC){x-a.x,y-a.y};}
}p[_SIZE+5];
int n;
double dis(VEC a,VEC b) {return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));}
double check(VEC a,VEC b) {return a*b;}
struct STACK{
VEC s[_SIZE+5];int cnt=0;
void push(VEC x) {s[++cnt]=x;}
void pop() {cnt--;}
VEC operator[] (const int &x) {return s[cnt-x+1];}
bool empty() {return !cnt;}
void calc(double &ans)
{
for (int i=2;i<=cnt;i++)
ans+=dis(s[i],s[i-1]);
}
int size() {return cnt;}
void print() {for (int i=1;i<=cnt;i++) printf("%.2lf %.2lf\n",s[i].x,s[i].y);puts("");}
};
STACK s;
bool cmp(VEC a,VEC b)
{
double temp=check(a-p[1],b-p[1]);
if (temp!=0) return temp>0;
return dis(a,p[1])<dis(b,p[1]);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
if (i!=1 && (p[i].y<p[1].y || (p[i].y==p[1].y && p[i].x<p[1].x))) swap(p[i],p[1]);
}
sort(p+2,p+n+1,cmp);
s.push(p[1]);
for (int i=2;i<=n;i++)
{
while (s.size()>1 && check(s[1]-s[2],p[i]-s[1])<=0) s.pop();
s.push(p[i]);
}
s.push(p[1]);//计算答案的时候记得将第一个点作为凸包终点加入栈中进行统计
double ans=0;
s.calc(ans);
printf("%.2lf\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理