计算几何Flag

人形自走Flagzxn再次上线
计算几何是不能一点都不会的。
即使NOI不出,省选不出,什么地方的考试都不出。
但是调试这种代码肯定会给我带来很大的好处。
而且……
像是裸的凸包/旋转卡壳的话,自己现在还不会写,就感觉有点尴尬了。
记得当时调<冷冻波>这个题目的时候,自己就在一个非常非常简单的地方犯各种奇奇怪怪的错误。
想了想,其实就是自己一点都不懂计算几何。
ACM的时候,全队卡死在一个圆的交的题上,导致没能出线。(虽然自己太弱,什么题都做不来)
NOIP随便来个乱七八糟的几何题的模拟赛,可以瞬间崩盘。


既然不会的话,就先要学。
(水平可见直线那个题我调了一小时敢信)
首先去学习凸包。
做大概5-6题之后,我们继续学习相关知识,如旋转卡壳等算法。
基础性的计算几何的东西,总不能到时候做一些本来只需要一点点的计算几何知识的题目的时候,死因在计算几何吧。


凸包:(下标从1开始)

#include <cstdio>
#include <cmath>
#include <algorithm>
#define Rep(i,n) for(int i = 1;i <= n;++ i)
#define Rep0(i,n) for(int i = 0;i < n;++ i)
#define Dwn(i,n) for(int i = n;i;-- i)
#define v edge[i].to
#define RepG(i,x) for(int i = head[x];~ i; i = edge[i].next)
#define fl edge[i].f
#define vfl edge[i ^ 1].f

using namespace std;
const double eps = 1e-7;
const int N = 100005;
int n,m,tot,id[N];
struct Point{double x,y;}p[N],stk[N];
int sgn(double x){return fabs(x) < eps ? 0 : (x > 0) ? 1 : -1;}
double sqr(double x){return x * x;}
double dist(Point a,Point b){return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
Point operator+(Point a,Point b){return (Point){a.x + b.x,a.y + b.y};};
Point operator-(Point a,Point b){return (Point){a.x - b.x,a.y - b.y};};
double dot(Point a,Point b){return a.x * b.x + a.y * b.y;}
double crs(Point a,Point b){return a.x * b.y - a.y * b.x;}
double crs(Point a,Point b,Point c){return crs((a - c),(b - c));}
bool cmp(Point a,Point b){return fabs(a.x - b.x) < eps ? a.y < b.y : a.x < b.x;}
void get()
{
    sort(p + 1,p + 1 + n,cmp);
    Rep(i,n)
    {
        while(tot > 1 && sgn(crs(stk[tot],p[i],stk[tot - 1])) <= 0)tot --;
        stk[++ tot] = p[i];//id[tot] = i;
    }
    int cur = tot;
    for(int i = n - 1;i;-- i)
    {
        while(tot > cur && sgn(crs(stk[tot],p[i],stk[tot - 1])) <= 0)tot --;
        stk[++ tot] = p[i];id[tot - 1] = i;
    }
    if(n > 1)tot --;
}
#define PI 3.14159265 
int main()
{
    double L,ans = 0;
    scanf("%d%lf",&n,&L);
    Rep(i,n)scanf("%lf%lf",&p[i].x,&p[i].y);
    get();
    for(int i = 2;i <= tot;++ i)ans += dist(stk[i],stk[i - 1]);
    ans += dist(stk[tot],stk[1]);
    ans += PI * 2 * L;
    printf("%.0f\n",ans);
    return 0;
}

就是先求个下凸壳,然后再求上凸壳就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值