半平面求交 - 洛谷 - P3194 [HNOI2008] 水平可见直线

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

往期相关背景点击前往

题目大意

题目链接
https://www.luogu.com.cn/problem/P3194

在直角坐标系中给定一些直线,然后从Y轴无穷大处往0处看,问可以看到哪些直线。

在这里插入图片描述

解析

在这里插入图片描述
通过观察可以发现,能看到的直线会形成一个开口凸包。

可以先对直线进行方向规定向右,然后进行半平面求交,凸包有效的边就是可以看到的直线。

代码

#include<stdio.h>
#include<cmath>
#include <algorithm>
#include <vector>
#include <list>
#include <cstring>
#include <deque>using namespace std;
const double EPS = 1e-12;const int N = 1e6 + 10;
const int M = 1e6 + 10;int cmp(double d) {if (abs(d) < EPS)return 0;if (d > 0)return 1;return -1;
}class Point {
public:double x, y;int id;Point() {}Point(double a, double b) :x(a), y(b) {}Point(const Point& p) :x(p.x), y(p.y), id(p.id) {}void in() {scanf("%lf %lf", &x, &y);}void out() {printf("%f %f\n", x, y);}double dis() {return sqrt(x * x + y * y);}double dis2() {return x * x + y * y;}Point operator -() const {return Point(-x, -y);}Point operator -(const Point& p) const {return Point(x - p.x, y - p.y);}Point operator +(const Point& p) const {return Point(x + p.x, y + p.y);}Point operator *(double d)const {return Point(x * d, y * d);}Point operator /(double d)const {return Point(x / d, y / d);}void operator -=(Point& p) {x -= p.x;y -= p.y;}void operator +=(Point& p) {x += p.x;y += p.y;}void operator *=(double d) {x *= d;y *= d;}void operator /=(double d) {this ->operator*= (1 / d);}bool operator<(const Point& a) const {return x < a.x || (abs(x - a.x) < EPS && y < a.y);}bool operator==(const Point& a) const {return abs(x - a.x) < EPS && abs(y - a.y) < EPS;}
};// 向量操作double cross(const Point& a, const Point& b) {return a.x * b.y - a.y * b.x;
}double dot(const Point& a, const Point& b) {return a.x * b.x + a.y * b.y;
}class Line {
public:Point front, tail;int ind;Line() {}Line(const Point& a, const Point& b) :front(a), tail(b) {}Line(const Point& a, const Point& b, int i) :front(a), tail(b), ind(i) {}
};int cmp(const Line& a, const Line& b) {auto ta = atan2(a.front.y - a.tail.y, a.front.x - a.tail.x);auto tb = atan2(b.front.y - b.tail.y, b.front.x - b.tail.x);return cmp(ta - tb);
}// 点在直线哪一边>0 左边,<0边
int SideJudge(const Line& a, const Point& b) {return cmp(cross(a.front - a.tail, b - a.tail));
}int LineSort(const Line& a, const Line& b) {int c = cmp(a, b);if (c)return c < 0;return SideJudge(b, a.front) > 0;
}/*
点p 到 p+r 表示线段1
点q 到 q+s 表示线段2
线段1 上1点用 p' = p+t*r (0<=t<=1)
线段2 上1点用 q' = q+u*s (0<=u<=1)
让两式相等求交点 p+t*r = q+u*s
两边都叉乘s
(p+t*r)Xs = (q+u*s)Xs
pXs + t*rXs = qXs
t = (q-p)Xs/(rXs)
同理,
u = (p-q)Xr/(sXr) -> u = (q-p)Xr/(rXs)以下分4种情况:
1. 共线,sXr==0 && (q-p)Xr==0, 计算 (q-p)在r上的投影在r长度上的占比t0,
计算(q+s-p)在r上的投影在r长度上的占比t1,查看[t0, t1]是否与范围[0,1]有交集。
如果t0>t1, 则比较[t1, t0]是否与范围[0,1]有交集。
t0 = (q-p)*r/(r*r)
t1 = (q+s-p)*r/(r*r) = t0 + s · r / (r · r)
2. 平行sXr==0 && (q-p)Xr!=0
3. 0<=u<=1 && 0<=t<=1 有交点
4. 其他u, t不在0到范围内,没有交点。
*/
pair<double, double> intersection(const Point& q, const Point& s, const Point& p, const Point& r) {// 计算 (q-p)Xrauto qpr = cross(q - p, r);auto qps = cross(q - p, s);auto rXs = cross(r, s);if (cmp(rXs) == 0)return { -1, -1 }; // 平行或共线// 求解t, u// t = (q-p)Xs/(rXs)auto t = qps / rXs;// u = (q-p)Xr/(rXs)auto u = qpr / rXs;return { u, t };
}Point LineCross(const Line& a, const Line& b) {Point dira = a.front - a.tail;Point dirb = b.front - b.tail;auto p = intersection(a.tail, dira, b.tail, dirb);return a.tail + dira * p.first;
}class HalfPlane {
public:vector<Line> lines;void addLine(const Line& a) {lines.push_back(a);}vector<int> run() {sort(lines.begin(), lines.end(), LineSort);vector<int> q(lines.size() + 10);vector<Point> t(lines.size() + 10);int l = -1, r = 0;q[0] = 0;for (int i = 1; i < lines.size(); ++i) {if (cmp(lines[i], lines[i - 1]) == 0)continue;while (r - l > 1 && SideJudge(lines[i], t[r]) <= 0)r--;while (r - l > 1 && SideJudge(lines[i], t[l + 2]) <= 0)l++;q[++r] = i;t[r] = LineCross(lines[q[r]], lines[q[r - 1]]);}/*while (r - l > 1 && SideJudge(lines[q[l + 1]], t[r]) < 0)r--;t[r+1] = LineCross(lines[q[l+1]], lines[q[r]]);r++;*/// 统计交点/*l++;vector<Point> ans(r-l);for (int i = 0; i < ans.size(); ++i) {ans[i] = t[i + l + 1];}*/vector<int> ans;for (int i = l + 1; i <= r; ++i) ans.push_back(lines[q[i]].ind);sort(ans.begin(), ans.end());return ans;}
};Point oiPs[N];void  solve() {int n;scanf("%d", &n);HalfPlane hp;int a, b;for (int i = 0; i < n; ++i) {scanf("%d%d", &a, &b);Line l(Point(1, a + b), Point(0, b), i + 1);hp.addLine(l);}auto ans = hp.run();for (auto x : ans) printf("%d ", x);
}int main() {solve();return 0;}/*
1
0 02
-1 0
-1 14
-1 0
-1 1
0 0
1 -110
1 2
5 8
7 6
-1 8
-8 9
-9 11
-3 -4
-5 7
8 7
9 1010
-8 10
-7 9
-6 8
-10 0
-5 7
-4 6
-3 5
-2 4
-1 3
0 0*/

本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/143334.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EDA实验------数控分频器设计(QuartusII)

目录 一、实验目的 二、实验原理 三、实验内容 四、实验步骤 五、注意事项 六、思考题 七、实验过程 分频器的基本原理 什么是分频器&#xff1f; 如何去分频&#xff1f; 1.创建新项目 2.创建Verilog文件&#xff0c;写入代码 3.连接电路 ​编辑 锁相环的创建 4…

ubuntu18.04安装google浏览器

下载google安装包 wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb 安装google浏览器 sudo dpkg -i google-chrome-stable_current_amd64.deb 执行安装 sudo apt-get -f install 启动浏览器 在应用程序中找到google图标点击运行

物联网AI MicroPython学习之语法 GPIO输入输出模块

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; GPIO 介绍 模块功能: GPIO通用输入输出。 接口说明 GPIO - 构建GPIO对象 函数原型&#xff1a;Pin(port, dir , pull)参数说明&#xff1a; 参数类型必选参数&#xff1f;说明portintY对应开发板的引脚号…

基础课4——客服中心管理者面临的挑战

客服管理者在当今的数字化时代也面临着许多挑战。以下是一些主要的挑战&#xff1a; 同行业竞争加剧&#xff1a;客服行业面临着来自同行业的竞争压力。为了获得竞争优势&#xff0c;企业需要不断提高自身的产品和服务质量&#xff0c;同时还需要不断降低成本、提高效率。然而…

【入门Flink】- 11Flink实现动态TopN

基本处理函数&#xff08;ProcessFunction&#xff09; stream.process(new MyProcessFunction())方法需要传入一个 ProcessFunction 作为参数&#xff0c;ProcessFunction 不是接口 &#xff0c; 而是一个抽象类 &#xff0c;继承了AbstractRichFunction&#xff0c;所有的处…

Oracle(2-2)Oracle Net Architecture

文章目录 一、基础知识1、Oracle Net Connections Oracle网络连接2、C/S Application Connection C/S应用程序连接3、OSI Communication Layers OSI通信层4、Oracle Protocol Support Oracle协议支持5、B/S Application Connections B/S应用程序连接6、TwoTypes JDBC Drivers 两…

Vue 2学习(路由、history 和 hash 模式、)-day014

一、路由简介 路由&#xff08;route&#xff09;就是一组 key-value 的对应关系多个路由&#xff0c;需要经过路由器&#xff08;router&#xff09;的管理 在 Vue 中也有路由&#xff0c;Vue 中的路由主要是通过 vue-rounter 这个插件库来实现&#xff0c;它的作用就是专门用…

力扣双周赛 -- 117(容斥原理专场)

class Solution { public:long long c2(long long n){return n > 1? n * (n - 1) / 2 : 0;}long long distributeCandies(int n, int limit) {return c2(n 2) - 3 * c2(n - limit 1) 3 * c2(n - 2 * limit) - c2(n - 3 * limit - 1);} };

Python+selenium自动化测试

批量执行完用例后&#xff0c;生成的测试报告是文本形式的&#xff0c;不够直观&#xff0c;为了更好的展示测试报告&#xff0c;最好是生成HTML格式的。 unittest里面是不能生成html格式报告的&#xff0c;需要导入一个第三方的模块&#xff1a;HTMLTestRunner 一、导入HTML…

Peoeasy机器人:原点无法重置问题

机械手在伺服关闭的模式下&#xff0c;插入定位插销&#xff0c;进入机构设定重置原点&#xff0c;发现PUU值没有变化 问题原因 台达软件版本比较多&#xff0c;每个版本重置原点的模式和马达偏差角的默认值是有一定差异的。再重置原点之前尽可能先确认一下重置原点的模式和马…

博流BL602芯片 - 烧录配置

硬件介绍 淘宝上买的核心板&#xff0c;大概结构如上。 直接插入电脑usb&#xff0c;即可实现供电、下载&#xff08;控制BOOT/EN&#xff09;、串口通讯 固件包 1、环境配置 1.1串口 开发板使用了 CH340G 的 USB 转串口芯片&#xff0c;自行安装CH340串口驱动。 1.2编译环境…

【Android】统一系统动画

需求&#xff1a;除panel动画效果为弹出之外&#xff0c;其余的应用效果为渐入渐出 从系统层面统一把控动画效果&#xff0c;而不是单个应用自己处理 Android系统版本&#xff1a;9.0 代码地址 \frameworks\base\core\res\res\values\styles.xml 当时看注释&#xff0c;以为…

iOS:何为空指针和野指针

一&#xff1a;什么是空指针和野指针 1、空指针 ①.没有存储任何内存地址的指针就成为空指针&#xff08;NULL指针&#xff09; ②.空指针就是被赋值为0的指针&#xff0c;在没有被具体初始化之前&#xff0c;其值为0. //以下都是空指针&#xff0c;eg: Person *p1 NULL; …

RGB转Bayer,一个小数点引发的血案

前几天写了一个RGB数据转Bayer格式的函数&#xff0c;经过测试功能正常。后来把这个函数用到一个数据库构建中&#xff0c;结果数据库出来的结果一直是一张黑图&#xff0c;追查了好几个小时&#xff0c;总算把这只虫子找出来了&#xff0c;原来是一个整数后面的小数点作祟。 …

⑦【MySQL】什么是约束?如何使用约束条件?主键、自增、外键、非空....

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 约束 ⑦【MySQL】约束条件1. 约束的基本使用2.…

Flutter笔记:使用Flutter构建响应式PC客户端/Web页面-案例

Flutter笔记 使用Flutter构建响应式PC客户端/Web页面-案例 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/detai…

软件工程-第7章 面向对象方法基础

第7章 面向对象方法基础 面向对象的基本概念 面向对象方法的世界观&#xff1a;一切系统都是由对象构成的&#xff0c;他们的相互作用、相互影响&#xff0c;构成了大千世界的各式各样系统。面向对象方法是一种以对象、对象关系等来构造软件系统模型的系统化方法。 面向对象 …

从0到0.01入门React | 009.精选 React 面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

Mac M3 芯片安装 Nginx

Mac M3 芯片安装 Nginx 一、使用 brew 安装 未安装 brew 的可以参考 【Mac 安装 Homebrew】 或者 【Mac M2/M3 芯片环境配置以及常用软件安装-前端】 二、查看 nginx 信息 通过命令行查看 brew info nginx可以看到 nginx 还未在本地安装&#xff0c;显示 Not installed …