UVa1318/LA2797 Monster Trap

题目链接

         本题是2003年ICPC亚洲区域赛会津(日本)赛区的H题

题意

        给出一些线段障碍,你的任务是判断怪物能否逃到无穷远处。如下图所示,左图无法逃出,右图的可以逃出。

        输入包含多组数据。每组数据第一行为整数n(1≤n≤100),即线段条数。以下n 行每行4 个整数,即一条线段两端的坐标。假定线段的长度均为正,坐标绝对值不超过50。假设任意两条线段最多只有一个公共点,无三线共点。任意两个交点的距离大于1e-5。输入结束标志为n=0。        

分析

       《训练指南》上的例题,按照其题解做,发现一个套模板的坑点:本题卡阈值!

        这里给出《训练指南》代码仓库上的源码(第10行)来说明坑点:

const double eps = 1e-12;

        如过把eps改为大于1e-12或者小于1e-14的值(比如1e-111e-15)再提交则WA,而eps写成1e-121e-131e-14则AC。

        根本原因在《训练指南》给出的计算几何模板里面的dcmpSegmentProperIntersectionOnSegment三个函数这里。

int dcmp(double x) {
    return abs(x) < eps ? 0 : (x < 0. ? -1 : 1);
}

bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) {
    double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);
    double c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
    return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}

bool OnSegment(const Point& p, const Point& a1, const Point& a2) { // 不含端点
    return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) < 0;
}

        OnSegment函数对dcmp的阈值eps要求低一些(不可太大也不可太小,中间范围即可),但本题的做法涉及把每条线段两端延长一点点(按题意延长量为1e-6合适,因为题木交代两个交点的距离在1e-5量级以上),这样就导致SegmentProperIntersection里面叉乘的结果可能很小,极端数据会小于eps。

        说一下解决方案:SegmentProperIntersection里面对叉乘直接判断符号,不用阈值。

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

bool SegmentProperIntersect(const Point& a1, const Point& a2, const Point& b1, const Point& b2) {
    double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);
    double c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
    // return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
    // 部分卡精度的题目需要直接判断正负号
    return sign(c1) * sign(c2) < 0 && sign(c3) * sign(c4) < 0;
}

        附一份测试数据和用python写的画图可视化分析数据的脚本方便读者debug。

AC代码

#include <iostream>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;

#define eps 1e-10
struct Point {
    double x, y;
    Point(double x = 0, double y = 0): x(x), y(y) {}
    void Normalize() {
        double l = sqrt(x*x + y*y); x /= l; y /= l;
    }
};
typedef Point Vector;

Vector operator+ (const Vector& A, const Vector& B) {
    return Vector(A.x + B.x, A.y + B.y);
}

Vector operator- (const Vector& A, const Vector& B) {
    return Vector(A.x - B.x, A.y - B.y);
}

Vector operator* (const 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);
}

double Cross(const Vector& A, const Vector& B) {
    return A.x * B.y - A.y * B.x;
}

double Dot(const Vector& A, const Vector& B) {
    return A.x * B.x + A.y * B.y;
}

int dcmp(double x) {
    return abs(x) < eps ? 0 : (x < 0. ? -1 : 1);
}

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

bool SegmentProperIntersect(const Point& a1, const Point& a2, const Point& b1, const Point& b2) {
    double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);
    double c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
    return sign(c1) * sign(c2) < 0 && sign(c3) * sign(c4) < 0;
}

bool OnSegment(const Point& p, const Point& a1, const Point& a2) {
    return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) < 0;
}

#define N 205
Point p[N]; int x[N], q[N], n, t; bool vis[N];

bool NotOnAnySegment(const Point& x) {
    for (int i=0; i<n; ++i) if (OnSegment(x, p[i], p[i+n])) return false;
    return true;
}

bool NotIntersectWithAnySegment(int u, int v) {
    for (int i=0; i<n; ++i) if (SegmentProperIntersect(p[i], p[i+n], p[u], p[v])) return false;
    return true;
}

bool solve() {
    memset(vis, t = 0, sizeof(vis));
    for (int i=0; i<n; ++i) {
        cin >> p[i].x >> p[i].y >> p[i+n].x >> p[i+n].y;
        Vector v = p[i+n] - p[i]; v.Normalize(); v = v*1e-6;
        p[i].x -= v.x; p[i].y -= v.y; p[i+n].x += v.x; p[i+n].y += v.y;
    }
    p[n<<1].x = p[n<<1].y = 0.; p[(n<<1)+1].x = -60.; p[(n<<1)+1].y = 60.; x[t++] = n<<1; x[t++] = (n<<1)+1;
    for (int i=0; i<n; ++i) {
        if (NotOnAnySegment(p[i])) x[t++] = i;
        if (NotOnAnySegment(p[i+n])) x[t++] = i+n;
    }
    int head = 0, tail = 1; q[0] = 0;
    while (head < tail) {
        int u = q[head++];
        for (int v=1; v<t; ++v) if (!vis[v] && NotIntersectWithAnySegment(x[u], x[v])) {
            if (v == 1) return false;
            vis[q[tail++] = v] = 1;
        }
    }
    return true;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    while (cin >> n && n) cout << (solve() ? "yes" : "no") << endl;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[C#]C# winform部署yolov8目标检测的openvino模型

【官方框架地址】 https://github.com/ultralytics/ultralytics 【openvino介绍】 OpenVINO&#xff08;Open Visual Inference & Neural Network Optimization&#xff09;是由Intel推出的&#xff0c;用于加速深度学习模型推理的工具套件。它旨在提高计算机视觉和深度学…

【漏洞复现】Hikvision SPON IP网络对讲广播系统命令执行漏洞(CVE-2023-6895)

文章目录 前言声明一、系统简介二、漏洞描述三、影响版本四、漏洞复现五、修复建议 前言 Hikvision Intercom Broadcasting System是中国海康威视&#xff08;Hikvision&#xff09;公司的一个对讲广播系统。 声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播…

C++PythonC# 三语言OpenCV从零开发(2):教程选择

文章目录 相关专栏前言视频教学和官方文档视频教程OpenCV 官方教程最终选择我的最终选择 相关专栏 C&Python&Csharp in OpenCV 前言 OpenCV 有官方的教程和简单的视频教程&#xff1a; OpenCV 官方教程 B站也有相关的视频教学 OpenCV4 C 快速入门视频30讲 - 系列合集 …

AI短视频制作:创意与技术的完美结合

文章目录 一、充分了解AI技术的应用范围和优势二、创意策划&#xff0c;确定作品主题和风格三、素材收集&#xff0c;丰富作品内容四、特效制作&#xff0c;提升作品视觉效果五、配音处理&#xff0c;增强作品表现力六、作品发布&#xff0c;扩大作品传播范围《AI短视频制作一本…

关于大模型学习中遇到的3

来源&#xff1a;网络 Embedding模型 随着大型语言模型的发展&#xff0c;以ChatGPT为首&#xff0c;涌现了诸如ChatPDF、BingGPT、NotionAI等多种多样的应用。公众大量地将目光聚焦于生成模型的进展之快&#xff0c;却少有关注支撑许多大型语言模型应用落地的必不可少的Embed…

React16源码: React中的renderRoot的源码实现

renderRoot 1 &#xff09;概述 renderRoot 是一个非常复杂的方法这个方法里处理很多各种各样的逻辑, 它主要的工作内容是什么&#xff1f;A. 它调用 workLoop 进行循环单元更新 遍历整个 Fiber Tree&#xff0c;把每一个组件或者 dom 节点对应的Fiber 节点拿出来单一的进行更…

RabbitMQ入门篇【图文并茂,超级详细】

&#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 &#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 前言 1.什么是MQ 2.理解MQ 3.生活…

去掉element-ui的el-table的所有边框+表头+背景颜色

实例: 1.去掉table表头(加上:show-header"false") <el-table:data"tableData":show-header"false"style"width: 100%"> </el-table> 2.去掉table所有边框 ::v-deep .el-table--border th.el-table__cell, ::v-deep .el…

Git教程学习:05 撤销操作

文章目录 1 撤销操作2 取消暂存的文件3 撤销对文件的修改 1 撤销操作 这里&#xff0c;我们将会学习几个撤销基本工具。 注意&#xff0c;有些撤销操作是不可逆的。 这是在使用 Git 的过程中&#xff0c;会因为操作失误而导致之前的工作丢失的少有的几个地方之一。 有时候我们…

win系统环境搭建(十五)——如何将Windows系统备份

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十五&#xff09;——如何将Windows系统备份 文章目录 win系统环境搭建&#xff08;十五&#xff09;——如何将Windows系统备份1.为什么要做备份&#xff1f;1.1 关于启动快速启动1.2 关于BitLocker1.3…

【0到1的设计之路】从C语言到二进制程序

C程序如何从源代码生成指令序列(二进制可执行文件) 预处理 -> 编译 -> 汇编 -> 链接 -> 执行 预处理 预处理 文本粘贴 #include <stdio.h> #define MSG "Hello \ World!\n" int main() {printf(MSG /* "hi!\n" */); #ifdef __riscvpr…

2.C语言——控制语句

控制语句 1.分支语句/判断语句if 语句if...else 语句if...else if...else语句 switch语句 2.循环语句 while 语句 do...while 语句 for 语句 3.转向语句 break continue go to 1.分支语句/判断语句 if 语句 if(boolean_expression) { /* 如果布尔表达式为真将执行的语句 */ } …

【已解决】namespace “Ui“没有成员 xxx

先说笔者遇到的问题&#xff0c;我创建一个QWidget ui文件&#xff0c;然后编辑的七七八八后&#xff0c;想要用.h与.cpp调用其&#xff0c;编译通过&#xff0c;结果报了这个错误&#xff0c;本方法不是普适性&#xff0c;但是确实解决了这个鸟问题。 问题来源 搭建ui后&…

【算法与数据结构】1049、LeetCode 最后一块石头的重量 II

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题需要得到石头之间两两粉碎之后的最小值&#xff0c;那么一个简单的思路就是将这堆石头划分成大小相…

python使用jupyter记笔记

目录 一、安装 二、运行jupyter 三、使用 四、记笔记 Jupyter Notebook&#xff08;此前被称为 IPython notebook&#xff09;是一个交互式笔记本&#xff0c;支持运行 40 多种编程语言。 Jupyter Notebook 的本质是一个 Web 应用程序&#xff0c;便于创建和共享程序文档&a…

ChatGPT与文心一言:AI助手之巅的对决

随着科技的飞速发展&#xff0c;人工智能助手已经渗透到我们的日常生活和工作中。 而在这个充满竞争的领域里&#xff0c;ChatGPT和文心一言无疑是最引人注目的两款产品。它们各自拥有独特的优势&#xff0c;但在智能回复、语言准确性、知识库丰富度等方面却存在差异。那么&am…

unity-声音与声效OLD

声音与声效 基本概念audio clipaudio listeneraudio source 基本操作如何创建音频源&#xff08;背景音乐&#xff09;如何在测试的时候关闭声音 常用代码一般流程如何在一个物体上播放多个音效如何在代码中延时播放多个声音如何在代码中停止音频的播放如何判断当前是否在播放音…

Linux 【C编程】 引入线程,线程相关函数

1.线程的引入 1.1使用线程同时读取键盘和鼠标 代码演示&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <termios.h> #include <fcntl.h> #include <string.h> // 读取…

可媲美Gen2的视频生成大一统模型;Vlogger根据用户描述生成分钟级视频;Vision Mamba提速2.8倍节省86.8%

本文首发于公众号&#xff1a;机器感知 可媲美Gen2的视频生成大一统模型&#xff1b;Vlogger根据用户描述生成分钟级视频&#xff1b;Vision Mamba提速2.8倍节省86.8% UniVG: Towards UNIfied-modal Video Generation Current efforts are mainly concentrated on single-obj…

00-Rust前言

问&#xff1a;为什么要近期想学习Rust? 答&#xff1a; Rust出来也是有一段时间了&#xff0c;从Microsoft吵着要重构他们的C"祖传代码"开始&#xff0c;Rust就披着“高效&#xff0c;安全”的头衔。而自己决定要学习Rust&#xff0c;是因为近期发现&#xff1a;与…