首页 > 其他分享 >RE:从零开始的计算几何生活

RE:从零开始的计算几何生活

时间:2023-11-09 22:13:23浏览次数:28  
标签:return double top stk RE 从零开始 vec 几何 const

RE:从零开始的计算几何生活

计算几何算法汇总

爱来自 yyc。

定义一些坏文明:

#define db double
const db eps = 1e-10;

误差计算:

int sign (double x) {
	return x > eps ? 1 : (x < -eps ? -1 : 0); 
}

向量:

struct vec {
	double x, y;
    void debug () { printf("%.3lf %.3lf\n", x, y); }
    vec operator + (const vec & t) const { return vec{x + t.x, y + t.y}; }
    vec operator - (const vec & t) const { return vec{x - t.x, y - t.y}; }
    vec operator * (const double & t) const { return vec{x * t, y * t}; }
    vec operator / (const double & t) const { return vec{x / t, y / t};}
    double len () { return sqrt(x * x + y * y); }
    double operator | (const vec & t) const {
		return x * t.x + y * t.y; 
	}
    double operator ^ (const vec & t) const {
		return x * t.y - y * t.x;
    }
} ;

数量积:

double operator | (const vec & t) const {
	return x * t.x + y * t.y; 
}

叉积:

double operator ^ (const vec & t) const {
	return x * t.y - y * t.x;
}

几何意义是两个向量围成的平行四边形的有向面积。如果是正的那么 \(\vec{b}\) 是 \(\vec{a}\) 逆时针转过来的,那么 \(\vec{a} \times \vec{b} = a.x * b.y - a.y * b.x\) 。

img

乐。

凸包

按照水平顺序排序。

考虑增量构造法。

怎样一个点才会被加入凸包。那么如果加入一个点的时候,可以包住以前的点显然才会加入凸包。

所以使用单调栈维护栈顶和栈顶底下的点就可以维护一个凸包乐。

如果成乐顺时针夹角,那么就弹掉栈顶加点。这样必然可以求得下凸壳。

乐。

通过!

#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l; i <= r; i ++)
#define per(i, r, l) for (int i = r; i >= l; i --)
#define db double

using namespace std;
typedef long long ll;

const int _ = 1e5 + 5, mod = 998244353;

const db eps = 1e-10;
int n, stk[_], top;
int sign (double x) {
	return x > eps ? 1 : (x < -eps ? -1 : 0); 
}
struct vec {
	double x, y;
    void debug () { printf("%.3lf %.3lf\n", x, y); }
    vec operator + (const vec & t) const { return vec{x + t.x, y + t.y}; }
    vec operator - (const vec & t) const { return vec{x - t.x, y - t.y}; }
    vec operator * (const double & t) const { return vec{x * t, y * t}; }
    vec operator / (const double & t) const { return vec{x / t, y / t};}
    double len () { return sqrt(x * x + y * y); }
    double operator | (const vec & t) const {
		return x * t.x + y * t.y; 
	}
    double operator ^ (const vec & t) const {
		return x * t.y - y * t.x;
    }
    bool operator == (const vec & t) { return !sign(x - t.x) && !sign(y - t.y); }
} p[_];
bool cmp (vec a, vec b) { return sign(a.x - b.x) == 0 ? a.y < b.y : a.x < b.x; }
double dis (vec x, vec y) {
	vec z = x - y;
	return z.len(); 
}
bool antilock (vec x, vec y, vec z) { return sign((x - z) ^ (y - z)) >= 0; }
int main() {
	/*
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);
	黛拉可玛莉·岗德森布莱德,一亿年一遇美少女。
	*/
	cin >> n;
	rep(i, 1, n) scanf("%lf%lf", & p[i].x, & p[i].y);
	sort(p + 1, p + 1 + n, cmp);
	n = unique(p + 1, p + 1 + n) - (p + 1);
	stk[1] = 1, stk[top = 2] = 2;
	rep(i, 3, n) {
		while(top >= 2 && !antilock(p[i], p[stk[top]], p[stk[top - 1]]))
			top --;
		stk[++ top] = i;
	} 
	double ret = 0;
	rep(i, 1, top - 1) ret += dis(p[stk[i]], p[stk[i + 1]]);
	stk[1] = n, stk[top = 2] = n - 1;
	per(i, n - 2, 1) {
		while(top >= 2 && !antilock(p[i], p[stk[top]], p[stk[top - 1]]))
			top --;
		stk[++ top] = i;
	}
	rep(i, 1, top - 1) ret += dis(p[stk[i]], p[stk[i + 1]]);
	printf("%.2lf", ret);
	return 0;
}

旋转卡壳

凸包内最远点对 \(\to\) 直径

定义凸包上的对踵点对 : 用两条平行直线卡着凸包转,着两条直线一定会卡住至少两个点,这两个点称为对踵点对。

img

旋 转 卡 壳。

引理(重要) : 只用考虑斜率恰好与凸包某条边相同的直线。

证明:感觉证明法。

考虑最远点也是随着边旋转的,所以边走边跑双指针即可。

注意维护点到直线的距离,可以使用叉积加面积法解决,但是这里固定乐一个边。

注意不能保留共线点即可。

#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l; i <= r; i ++)
#define per(i, r, l) for (int i = r; i >= l; i --)
#define db double

using namespace std;
typedef long long ll;

const int _ = 1e5 + 5, mod = 998244353;

const db eps = 1e-7;
int n, stk[_], top;
int sign (double x) {
	return x > eps ? 1 : (x < -eps ? -1 : 0); 
}
struct vec {
	double x, y;
    void debug () { printf("%.3lf %.3lf\n", x, y); }
    vec operator + (const vec & t) const { return vec{x + t.x, y + t.y}; }
    vec operator - (const vec & t) const { return vec{x - t.x, y - t.y}; }
    vec operator * (const double & t) const { return vec{x * t, y * t}; }
    vec operator / (const double & t) const { return vec{x / t, y / t};}
    double len () { return sqrt(x * x + y * y); }
    double operator | (const vec & t) const {
		return x * t.x + y * t.y; 
	}
    double operator ^ (const vec & t) const {
		return x * t.y - y * t.x;
    }
    bool operator == (const vec & t) { return !sign(x - t.x) && !sign(y - t.y); }
} p[_];
bool cmp (vec a, vec b) { return sign(a.x - b.x) == 0 ? a.y < b.y : a.x < b.x; }
double dis (vec x, vec y) {
	vec z = x - y;
	return z.len(); 
}
bool antilock (vec x, vec y, vec z) { return sign((x - z) ^ (y - z)) > 0; }
double su (vec x, vec y, vec z) { return abs((x - y) ^ (x - z)); }

int tot;
vec v[_];
void hull () {
	rep(i, 1, n) scanf("%lf%lf", & p[i].x, & p[i].y);
	sort(p + 1, p + 1 + n, cmp);
	stk[1] = 1, stk[top = 2] = 2;
	rep(i, 3, n) {
		while(top >= 2 && !antilock(p[i], p[stk[top]], p[stk[top - 1]]))
			top --;
		stk[++ top] = i;
	} 
	rep(i, 1, top) v[++ tot] = p[stk[i]];
	stk[1] = n, stk[top = 2] = n - 1;
	per(i, n - 2, 1) {
		while(top >= 2 && !antilock(p[i], p[stk[top]], p[stk[top - 1]]))
			top --;
		stk[++ top] = i;
	}
	rep(i, 2, top - 1) v[++ tot] = p[stk[i]];
}
double RotateHull () {
	double ans = 0;
	if (tot == 2) { ans = dis(v[1], v[2]); return ans; }
	v[0] = v[tot];
	int cur = 2;
	rep(i, 1, tot) {
		while(su(v[cur % tot + 1], v[i], v[i - 1]) > eps + su(v[cur], v[i], v[i - 1]))
			cur = cur % tot + 1;
		ans = max(ans, dis(v[cur], v[i]));
		ans = max(ans, dis(v[cur], v[i - 1]));
	}
	return ans;
}
int main() {
	/*
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);
	黛拉可玛莉·岗德森布莱德,一亿年一遇美少女。
	*/
	cin >> n;
	hull();
	double diameter = RotateHull();
	printf("%.0lf", diameter);
	return 0;
}

闵可夫斯基和

\(\{a + b | a \in A, b \in B \}\)

具体来说就是把 \(B\) 中的每个点当成向量,沿着这个走所到达的所有点集。

img

乐。

凸壳的话,两个凸壳的闵可夫斯基和是凸壳。

结论 : 将两个凸包上的边按照极角序顺次连接即可得到答案。

「JSOI2018战争」

题面略去。

考虑求 \(B\) 和 \(-A\) 的闵可夫斯基和,判定是不是在 \(x\) 上即可。

半平面交

乐。

标签:return,double,top,stk,RE,从零开始,vec,几何,const
From: https://www.cnblogs.com/Custlo/p/17822995.html

相关文章

  • C++ ubuntu install libpq-fe.h PGconn PQconnectdb PGresult PQexec PQnfields P
    1.Installlibpq-devsudoaptinstalllibpq-devlocatelibpq-fe.h/usr/include/postgresql/libpq-fe.h 2.main.cpp#include<chrono>#include<fstream>#include<iomanip>#include<iostream>#include<sstream>#include<......
  • 【刷题笔记】104. Maximum Depth of Binary Tree
    题目Givenabinarytree,finditsmaximumdepth.Themaximumdepthisthenumberofnodesalongthelongestpathfromtherootnodedowntothefarthestleafnode.Note:Aleafisanodewithnochildren.Example:Givenbinarytree[3,9,20,null,null,15,7],......
  • [题解] P5901 [IOI2009] Regions
    P5901[IOI2009]Regions给你一棵树,每个点有颜色\(h_i\)。多次询问,每次询问有多少对\((u,v)\)满足\(u\)是\(v\)的祖先且\(u\)的颜色是\(r_1\)且\(v\)的颜色是\(r_2\)。\(n,q\le2\times10^5,h_i\le2.5\times10^4\)。总颜色数一定,考虑对颜色的出现次......
  • Pset_AnnotationSurveyArea
    Pset_AnnotationSurveyAreaPSET_TYPEDRIVENOVERRIDE / IfcAnnotation / SurveyArea注释测量区域:指定要指定给测量点集或生成的曲面面片的测量方法的特定特性: Définitiondel'IAI:spécifiedespropriétésparticulièresdeméthodesderelevéàrel......
  • Soil Erosion Maesures
    Soilerosionisaseriousenvironmentalissue.Stepsshouldbetakentocurbthisproblem.Followingaresomeofthemethodsofsoilerosionprevention: 1.IncreasevegetationcoverIncreasingvegetationcovercaneffectivelypreventsoilerosion,impro......
  • HttpResponse,render,redirect
    fromdjango.shortcutsimportrender,HttpResponse,redirectHttpResponse主要用于直接返回字符串类型的数据defindex(request):returnHttpResponse('hello')#pass#相当于returnNone  render主要用于返回html页面并且支持模板语法模板......
  • Introducing the core concepts of Kafka
    IntroductionI havelearntthekafkasince5years,IbelieveIlearndsomthing,Itisontimeforimprovingenglish.SoIdecidedtopickupmyblogs,towritingsomeconceptsofkafkaforconsolidatingmemory.Bytheway, makingmyenglishbetter.How......
  • RLHF · PBRL | PEBBLE:通过 human preference 学习 reward model
    论文题目:PEBBLE:Feedback-EfficientInteractiveReinforcementLearningviaRelabelingExperienceandUnsupervisedPre-training,貌似是ICML2021的文章。本博客为论文阅读笔记,【不能代替】阅读原文的工作量。原文写的也很好,是AI顶会的风格,相对容易读懂。阅读材料:p......
  • 无涯教程-批处理 - Creating Files函数
    新文件的创建是在重定向过滤器>的帮助下完成的,该过滤器可用于将任何输出重定向到文件。@echooffecho"Hello">C:\new.txt如果文件new.txt在C:\中不存在,则将在上述命令将创建new.txt文件,并将hello写入文件。参考链接https://www.learnfk.com/batch-script/batch-script-crea......
  • Error read ECONNRESET at TCP.onStreamRead报错的问题
    背景另一个同事在本地执行npmrunserve后,服务起来后,隔一段时间就会报错。然后我这边拉了代码,然后npmrunserve跑了下,发现也报错了。根本没有隔一段时间,而是直接跑不起来了。具体如下截图所示: 分析过程看报错信息,貌似是说socket服务监听和发送消息的过程出现问题了。然......