人形自走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;
}
就是先求个下凸壳,然后再求上凸壳就行了。