代码中的板子参考了繁凡和俊杰带佬的板子

二维基础

A.计算几何spj hacker

题意:

输入一组数a,b使无论ans为任何数,以下函数都返回AC。

// a and b are outputed by the contestant
// ans is provided by the jury
int check(int a,int b,double ans)
{double t=(double)a/(double)b;if(fabs(t-ans)>1e-9)return WA;return AC;
}

题解:


当a/b为nan值时,返回True。

代码:

//php
0 0

B.Winding Number

题意:

牛妹沿着nnn个点走,询问牛牛在某点观察到牛妹逆时针走的圈数与顺时针的圈数之差。

题解:

回转数板子

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
typedef pair<bool, int>Pr;
//constexpr double eps = 1e-8;
constexpr long long eps=0;
constexpr double PI = 3.1415926535897932384l;template<typename T> struct point
{T x, y;bool operator==(const point& a) const { return (abs(x - a.x) <= eps && abs(y - a.y) <= eps); }bool operator<(const point& a) const { if (abs(x - a.x) <= eps) return y < a.y - eps; return x < a.x - eps; }point operator+(const point& a) const { return { x + a.x,y + a.y }; }point operator-(const point& a) const { return { x - a.x,y - a.y }; }point operator-() const { return { -x,-y }; }point operator*(const T k) const { return { k * x,k * y }; }point operator/(const T k) const { return { x / k,y / k }; }T operator*(const point& a) const { return x * a.x + y * a.y; } //点乘 DotT operator^(const point& a) const { return x * a.y - y * a.x; } //叉乘 Cross// 1:左  -1:右  0:线上//auto的原理就是根据后面的值,来自己推测前面的类型是什么。//return *this返回当前对象, return this返回当前对象的地址(指向当前对象的指针)int toleft(const point& a) const { const auto t = (*this) ^ a; return (t > eps) - (t < -eps); }T len2() const { return (*this) * (*this); }T dis2(const point& a) const { return (a - (*this)).len2(); }double len() const { return sqrt(len2()); }double dis(const point& a) const { return sqrt(dis2(a)); }//夹角double ang(const point& a) const { return acos(max(-1.0, min(1.0, ((*this) * a) / (len() * a.len())))); }//逆时针旋转radpoint rot(const double rad) const { return { x * cos(rad) - y * sin(rad),x * sin(rad) + y * cos(rad) }; }
};using Point = point<ll>;template<typename T> struct line
{point<T> p, v;bool operator==(const line& a) const { return v.toleft(a.v) == 0 && v.toleft(p - a.p) == 0; }int toleft(const point<T>& a) const { return v.toleft(a - p); }//直线交点point<T> inter(const line& a) const { return p + v * ((a.v ^ (p - a.p)) / (v ^ a.v)); }//点到直线的距离double dis(const point<T>& a) const { return abs(v ^ (a - p)) / v.len(); }//a在直线上的投影点point<T> proj(const point<T>& a) const { return p + v * ((v * (a - p)) / (v * v)); }
};using Line = line<ll>;template<typename T> struct polygon
{vector<Point> p;//返回下一个点和前一个点//size_t可理解为unsigned int,应为数组下标类型inline size_t nxt(const size_t i) const { return i == p.size() - 1 ? 0 : i + 1; }inline size_t pre(const size_t i) const { return i == 0 ? p.size() - 1 : i - 1; }pair<bool, int> winding(const Point& a) const{int cnt = 0;for (size_t i = 0; i < p.size(); i++){Point u = p[i], v = p[nxt(i)];if (abs((a - u) ^ (a - v)) <= eps && (a - u) * (a - v) <= eps) return { true,0 };//点在边上if (abs(u.y - v.y) <= eps) continue;Line uv = { u,v - u };if (u.y < v.y - eps && uv.toleft(a) <= 0) continue;//该射线与边无交点if (u.y > v.y + eps && uv.toleft(a) >= 0) continue;//计算wn数if (u.y < a.y - eps && v.y >= a.y - eps) cnt++;if (u.y >= a.y - eps && v.y < a.y - eps) cnt--;}return { false,cnt };}//边长double circ() const{double sum = 0;for (size_t i = 0; i < p.size(); i++) sum += p[i].dis(p[nxt(i)]);return sum;}T area2() const{T sum = 0;for (size_t i = 0; i < p.size(); i++) sum += p[i] ^ p[nxt(i)];return abs(sum);}
};using Polygon = polygon<ll>;int n, m;int main() {cin >> n;Polygon P;for (int i = 0; i < n; i++) {int x, y; cin >> x >> y;P.p.push_back({ x,y });}cin >> m;while (m--) {int sx, sy; cin >> sx >> sy;Pr S = P.winding({ sx,sy });if (S.first)cout << "EDGE\n";else cout << S.second << "\n";}return 0;
}

C.Mr. Main and Windmills

代码:

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<bits/stdc++.h>
#define db double
using namespace std;
const int maxn = 1e3 + 10;
const int inf = 1e9;
double nx[maxn], ny[maxn];
int sx, sy, tx, ty;
int N, M;struct Point {double x, y;Point(double x = 0, double y = 0) :x(x), y(y) {}
};vector<Point>vec[maxn];
vector<Point>vec1[maxn];typedef Point Vector;Vector operator + (Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);
}Vector operator - (Point A, Point B) {return Vector(A.x - B.x, A.y - B.y);
}Vector operator * (Vector A, double p) {return Vector(A.x * p, A.y * p);
}Vector operator / (Vector A, double p) {return Vector(A.x / p, A.y / p);
}struct Line {//直线定义Point v, p;Line(Point v, Point p) :v(v), p(p) {}Point point(double t) {//返回点P = v + (p - v)*treturn v + (p - v) * t;}
};double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;
}Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {Vector u = P - Q;double t = Cross(w, u) / Cross(v, w);return P + v * t;
}double Dot(Vector A, Vector B) {return A.x * B.x + A.y * B.y;
}const double eps = 1e-15;int dcmp(double x, double y) {if (fabs(x - y) < eps)return 0;if (x > y)return 1;return -1;
}int sgn(double x) {if (fabs(x) < eps)return 0;if (x < 0)return -1;return 1;
}bool OnSegment(Point p, Point a1, Point a2) {return  sgn(Dot(a1 - p, a2 - p)) < 0 ;//&& sgn(Cross(a1 - p, a2 - p)) == 0;
}bool up(Point a, Point b) {return a.x > b.x;
}bool low(Point a, Point b) {return a.x < b.x;
}int main() {cin >> N >> M;cin >> sx >> sy >> tx >> ty;Point S(sx, sy);Point T(tx, ty);Point P[maxn];Line car(S, T);for (int i = 1; i <= N; i++) {cin >> P[i].x >> P[i].y;}int f = 0;if (sx > tx)f = 1;for (int i = 1; i <= N; i++) {for (int j = 1; j <= N; j++) {Line feng(P[i], P[j]);if (i == j)continue;if (Cross(S - T, P[i] - P[j]) == 0)continue;Point d = GetLineIntersection(S, T - S, P[i], P[j] - P[i]);if (OnSegment(d, S, T))vec[i].push_back(d);}int len = vec[i].size();if (f)sort(vec[i].begin(), vec[i].end(), up);else sort(vec[i].begin(), vec[i].end(), low);}while (M--) {int p, k; cin >> p >> k;int tt=vec[p].size();if (tt < k)cout << -1 << endl;else printf("%.10f %.10f\n", vec[p][k - 1].x, vec[p][k - 1].y);}return 0;
}

E.Operation Love

题意:

在二维坐标图给出一个手掌状图形,判断该图形是左手还是右手。

题解:

枚举所有线段,通过线段长度找到A,B,C三个点,若BC⃗\vec{BC}BC在AB⃗\vec{AB}AB的逆时针方向为左手,否则为右手。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps = 1e-6;struct Point {double x, y;Point(double x = 0, double y = 0) :x(x), y(y) {}
};int sgn(double x) {if (fabs(x) < eps)return  0;if (x < 0)return -1;return 1;
}typedef Point Vector;Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (Point A, Point B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); }
Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }
bool operator < (const Point& a, const Point& b) { return a.x < b.x || (a.x == b.x && a.y < b.y); }
bool operator ==(const Point& a, const Point& b) { return !sgn(a.x - b.x) && !sgn(a.y - b.y); }//点积,可用于判断角度
double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//叉积
double Cross(Vector A, Vector B) { return A.x * B.y - B.x * A.y; }//模长
double Length(Vector A) { return sqrt(Dot(A, A)); }//判断 bc 是不是在 ab 的逆时针方向,向量夹角<90
bool ToLeftTest(Point a, Point b, Point c) { return Cross(b - a, c - b) > 0; }int T;int main() {ios::sync_with_stdio(0);cin >> T;while (T--) {Point p[30], P1, P2, P3, P4;for (int i = 1; i <= 20; i++)cin >> p[i].x >> p[i].y;p[21] = p[1], p[22] = p[2];p[0] = p[20];for (int i = 1; i <= 20; i++) {double L = Length(p[i + 1] - p[i]);if (L - 8.5 > eps) {// P1 = p[i], P2 = p[i + 1];double L1 = Length(p[i - 1] - p[i]), L2 = Length(p[i + 2] - p[i + 1]);if (L2 - L1 > eps)P1 = p[i], P2 = p[i + 1], P3 = p[i - 1];if (L1 - L2 > eps)P1 = p[i + 1], P2 = p[i], P3 = p[i + 2];break;}}if (!ToLeftTest(P2, P1, P3))cout << "right\n";else cout << "left\n";}return 0;
}

F.三角碰撞

题意

在一个三角形内,小球具有一个起始位置,方向及速度,遇到三角形的边会发生反弹,询问反弹 K 次的时间。

题解

大部分的反射问题都可以通过,将扩大延长原有图像的方法解决。

如图,我们可以把问题转化成一条具有方向的射线,需要多长时间,刚好与图中的三种直线有 k 个交点。

我们先看第一种直线。

我们只需要二分时间,得到该射线的终点,计算该条线段在y轴上的投影是三角形的高的几倍(红线与X轴之间蓝线的数量),倍数即是交点数。

对于第二,三种直线,我们需要通过坐标系变换,得到新的坐标,可通过第一种直线的方法解决。

坐标系变换,即是将X,Y轴逆时针旋转120°和240°,变换公式如下

[cos⁡θ−sin⁡θsin⁡θcos⁡θ][axay]=[cos⁡θax−sin⁡θaysin⁡θax+cosθay]\begin{bmatrix} \cos\theta&-\sin\theta\\ \sin\theta&\cos\theta\\ \end{bmatrix} \begin{bmatrix} a_x\\ a_y\\ \end{bmatrix}= \begin{bmatrix} \cos\theta a_x-\sin\theta a_y\\ \sin\theta a_x+cos\theta a_y\\ \end{bmatrix} [cosθsinθ​−sinθcosθ​][ax​ay​​]=[cosθax​−sinθay​sinθax​+cosθay​​]

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps = 1e-5;
const double gen3 = 1.7320508075688772935;
int T;
double L, x, y, vx, vy, k;bool ok(double len) {double res = 0, d = gen3 * L / 2.0;res += abs(floor((y + (len * vy)) / d));double py = fabs((-y - gen3 * x + d) / 2), pvy = (-vy - gen3 * vx) / 2;res+= abs(floor((py + (len * pvy)) / d));py = fabs((-y + gen3 * x + d) / 2), pvy = (-vy + gen3 * vx) / 2;res += abs(floor((py + (len * pvy)) / d));return res >= k;
}int main() {cin >> T;while (T--) {cin >> L >> x >> y >> vx >> vy >> k;double lb = 0, rb = 1e11;double mid = 0;while (rb - lb > eps) {mid = (rb + lb) / 2;if (ok(mid))rb = mid;else lb = mid;}printf("%.10f\n",mid);}return 0;
}

G.Magic Rabbit

题意

有三种体积相同,含有X溶液$ a_i ml/l$,Y溶液 biml/lb_i ml/lbi​ml/l的混合溶液,询问能否得到题目给出的不同浓度的混合溶液。

题解

我们在坐标系中将点描出并连起来,会发现这个其实是一个线性规划问题,坐标系中围成的区域就是能够配出的溶液配比。

因此,这道题可以转化成求某点是否在三角形内。

特别的是,这个三角形可能是退化的三角形。

我们需要通过 to_left 测试判断该点是否都在所有边的左边或者右边,或者在某一条边上即可。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps = 1e-4;
struct Point { double x, y; };
vector<Point>P;int to_left(Point a, Point b, Point c) {Point X = { b.x - a.x,b.y - a.y }, Y = { c.x - a.x,c.y - a.y };double ans = X.x * Y.y - X.y * Y.x ;double res = X.x * Y.x + Y.y * X.y;if (abs(ans) < eps) {return 0;}else if (ans > 0)return 1;return -1;
}int main() {for (int i = 0; i < 3; i++) {Point p; cin >> p.x >> p.y;P.push_back(p);}P.push_back(P[0]);int T; cin >> T;while (T--) {Point p; cin >> p.x >> p.y;int f1 = 0, f2 = 0, f = 0;for (int i = 0; i < 3; i++) {int cnt = to_left(P[i], P[i + 1], p);if (cnt == 1)f1++;else if (cnt == -1)f2++;else {if (p.x >= min(P[i].x, P[i + 1].x) && p.x <= max(P[i].x, P[i + 1].x) && p.y >= min(P[i].y, P[i + 1].y) && p.y <= max(P[i].y, P[i + 1].y)) {f = 1;}}}if (f1 == 3 || f2 == 3 || f == 1)cout << "YES\n";else cout << "NO\n";}return 0;
}

极角排序

A.Sort Points by Argument

题意

对每个点的极角进行排序

板子题

题解

简单解释一下板子

我们将平面分为五个部分,分别为 x 轴以下,原点,x 轴正半轴,x 轴以上,x 轴以上。

对于某一部分通过叉积来判断大小。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
//constexpr double eps = 1e-8;
constexpr long long eps = 0;
constexpr double PI = 3.1415926535897932384l;template<typename T> struct point
{T x, y;bool operator==(const point& a) const { return (abs(x - a.x) <= eps && abs(y - a.y) <= eps); }bool operator<(const point& a) const { if (abs(x - a.x) <= eps) return y < a.y - eps; return x < a.x - eps; }point operator+(const point& a) const { return { x + a.x,y + a.y }; }point operator-(const point& a) const { return { x - a.x,y - a.y }; }point operator-() const { return { -x,-y }; }point operator*(const T k) const { return { k * x,k * y }; }point operator/(const T k) const { return { x / k,y / k }; }T operator*(const point& a) const { return x * a.x + y * a.y; } //点乘 DotT operator^(const point& a) const { return x * a.y - y * a.x; } //叉乘 Cross// 1:左  -1:右  0:线上//auto的原理就是根据后面的值,来自己推测前面的类型是什么。//return *this返回当前对象, return this返回当前对象的地址(指向当前对象的指针)int toleft(const point& a) const { const auto t = (*this) ^ a; return (t > eps) - (t < -eps); }T len2() const { return (*this) * (*this); }T dis2(const point& a) const { return (a - (*this)).len2(); }double len() const { return sqrt(len2()); }double dis(const point& a) const { return sqrt(dis2(a)); }//夹角double ang(const point& a) const { return acos(max(-1.0, min(1.0, ((*this) * a) / (len() * a.len())))); }//逆时针旋转radpoint rot(const double rad) const { return { x * cos(rad) - y * sin(rad),x * sin(rad) + y * cos(rad) }; }
};using Point = point<ll>;bool argcmp(const Point& a, const Point& b) {auto quad = [](const Point& a) {if (a.y < -eps)return 1;if (a.y > eps)return 4;if (a.x < -eps)return 5;if (a.x > eps)return 3;return 2;};int qa = quad(a), qb = quad(b);if (qa != qb)return qa < qb;auto t = a ^ b;//极轴排序//if (abs(t) <= eps)return a * a < b* b - eps;return t > eps;
}ll n, x, y;
vector<Point>vec;int main() {cin >> n;for (int i = 0; i < n; i++) {Point p; cin >> p.x >> p.y;vec.push_back(p);}sort(vec.begin(), vec.end(), argcmp);for (int i = 0; i < vec.size(); i++) {cout << vec[i].x << " " << vec[i].y << "\n";}return 0;
}

计算几何从入门到入土(题目)相关推荐

  1. 计算几何从入门到入土(一)

    牛客计算几何班笔记 第一章 导论 概况 题目类型 包含三种: 判定 判断是否,比如是否有交点 计数 求交点,面积等 列举 圆与直线交点坐标 工具 https://csacademy.com/app/g ...

  2. rocketmq怎么保证消息一致性_从入门到入土(三)RocketMQ 怎么保证的消息不丢失?...

    精彩推荐 一百期Java面试题汇总SpringBoot内容聚合IntelliJ IDEA内容聚合Mybatis内容聚合 接上一篇:RocketMQ入门到入土(二)事务消息&顺序消息 面试官常常 ...

  3. Activiti工作流从入门到入土:完整Hello World大比拼(Activiti工作流 API结合实例讲解)

    文章源码托管:https://github.com/OUYANGSIHAI/Activiti-learninig 欢迎 star !!! 本来想着闲来无事,前面在项目中刚刚用到了工作流 Activit ...

  4. activiti api文档_【白银人机】Activiti 工作流从入门到入土:完整 hello world 大比拼(API 结合实例讲解)...

    点击上方"好好学java",选择"置顶"公众号 重磅资源.干货,第一时间送达 重磅推荐  ① 纯福利 | 公众号资源大汇总,一年才一次! ② 重磅!!2018年 ...

  5. 从入门到入土(十)RocketMQ集群流程以及核心概念

    精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 Mybatis内容聚合 接上一篇:从入门到入土(九)手摸手教你搭建RocketMQ双主双从同步集群 ...

  6. 从入门到入土(九)手摸手教你搭建RocketMQ双主双从同步集群,不信学不会!...

    精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 Mybatis内容聚合 接上一篇:从入门到入土(八)RocketMQ的Consumer是如何做的负 ...

  7. 从入门到入土(八)RocketMQ的Consumer是如何做的负载均衡的

    精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 Mybatis内容聚合 接上一篇:RocketMQ入门到入土(七 )为什么同一个消费组设置不同ta ...

  8. RocketMQ入门到入土(七 )为什么同一个消费组设置不同tag会出现奇怪现象

    精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 Mybatis内容聚合 接上一篇:RocketMQ入门到入土(六)发消息的时候选择queue的算法 ...

  9. RocketMQ入门到入土(六)发消息的时候选择queue的算法有哪些?

    精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 Mybatis内容聚合 接上一篇:RocketMQ入门到入土(五)消息持久化存储源码解析 一.说明 ...

最新文章

  1. PTAM增强现实相关
  2. 锚文本对网站SEO优化有什么帮助?
  3. EOS 源代码解读 (2)插件-流程
  4. ASP.Net MVC 在ajax接收controller返回值为Json数据
  5. 一些有趣的三方开源库
  6. SAP 电商云 FooterNavigationComponent 的设计细节
  7. mdAAPP:安装后会一直存在手机中,安装数据及缓存都会占用大量内存,而且各家全家桶APP之间都有一些藕断丝连的唤醒关系。 小程序:不需要安装在手机上,微信有严格的小程序内存管理机制,和微信共用内存使
  8. 秋招面试我去了拼多多,直接被问JVMGC底层原理和算法,我吊打面试官
  9. python你的人生_人生苦短:运行你的第一个 Python 脚本
  10. 运用网络管理工具主动纠错
  11. Mysql : InnoDB: Table flags are 0 in the data dictionary but the flags in file ./ibdata1 are 0x4800!
  12. 特斯拉皮卡,会大卖吗?
  13. Linux与云计算——第二阶段Linux服务器架设 第七章:网站WEB服务器架设—日志分析平台...
  14. Eclipse 快捷键设置
  15. 公摊面积用计算机怎么计算,公摊面积计算(公摊面积计算器)
  16. 黄油刀 Butterknife的使用准备工作
  17. JAVA#泛型'学习札记
  18. jpg转bmpbmp转jpg
  19. Unity项目-黑魂复刻(三)玩家控制器(跳跃)
  20. 生鲜新零售异军突起,科技才是核心驱动

热门文章

  1. 国内网络摄像机的端口及RTSP地址
  2. android,js,各种软件列表
  3. pads option选项卡下部分英文释义
  4. HPP结合PHP解析URL特性的SQL注入题目
  5. c语言作业 万能公式,按照下面的通项公式计算: sin(x)=x-x3/3!+x5/5!-x7/7!+… 直到最后一项的绝对值小于10-7为止。 用C程序编写正弦...
  6. div id与div class用法讲解
  7. springboot + vue3实现视频播放Demo(video.js Vue3-video-play视频播放器)
  8. 使用ABBYY FineReader 12心得体会总结
  9. python爬取必应首页壁纸,Windows每日自动运行
  10. 基于stm32的智能家居项目