UVa11726 Crime Scene

题目链接

         UVa11726 - Crime Scene

题意

        给定n(n≤100)个物体,每个物体都是一个圆或者k(k≤10)边形,用长度尽量小的绳子把它们包围起来。

分析

        孟加拉国Manzurur Rahman Khan (Sidky)大神出的难题,大神毕业于BUET(Bangladesh University of Engineering and Technology)。

        几何图形集合的凸包问题(凸包有两个最优性:长度最短;面积最小),本题的基本图形有圆,所以可以这么做:

        求出所有点和圆的切点,然后所有的点和原有的点一起做一次凸包,求出凸包的边长,如果连续的两个点都是同一个圆上的切点,计算长度的方式就要变成求弧长。

        这里不细说取巧的方法,而是详细探讨几何图形集合的凸包问题的一般求法,姑且叫滚边法吧:在所有图形中找到最低点,多个图形包含最低点时任取一个作为起点即可,初始时假想从起点水平往右的向量作为当前向量,找出逆时针最小旋转量使其刚好贴到下一个图形某点上,下一个图形如果是圆,则可以绕着切点逆时针转一定角度(注意:可能会转超过180度)再贴到其他图形的某一点上,依此不停滚边操作,直到回贴到起点。

        接下来说一些细节,先看这一份数据:

10
2
c 0 0 2
p 4 -1 2 1 2 1 -2 -1 -2
1
c 0 0 3
2
c 0 0 2
c 10 10 1
5
c 0 0 1
c 10 0 1
c 0 10 1
c 10 10 1
p 4 4 4 5 5 6 4 5 8
3
c 0 0 2
c 2 2 2
p 3 -1 2 1 4 3 -1
3
p 3 -2 5 2 5 4 8
c 5 -8 7
c -10 -1 9
4
p 2 -1 -8 -9 10
p 1 -5 -7
c -1 2 9
c 7 -7 1
3
p 2 9 2 -1 -5
p 4 9 -4 8 -4 -4 7 -3 -7
c 2 3 7
5
p 2 5 2 -1 -9
c 9 -7 8
p 2 -9 9 -2 9
c -4 1 8
p 3 -10 -9 4 3 -7 -9
6
p 1 1 -10
p 1 2 5
p 1 -5 2
c 3 -1 1
p 7 8 -4 -8 9 -1 10 -4 -5 -6 9 -9 -6 -9 -1
c -3 -6 4

        其正确输出应该是:

Case #1: 13.148009
Case #2: 18.849556
Case #3: 37.779789
Case #4: 46.283185
Case #5: 18.749469
Case #6: 87.092793
Case #7: 63.571176
Case #8: 51.636719
Case #9: 84.282670
Case #10: 59.374851

        以上结果可以利用可视化脚本画图再手算检验。

        后面几条数据容易出错,调试发现坑在double精度及反三角函数acos这里,acos函数传参必须严格在[-1,1]区间,否则会得到nan,因此可以这样处理:

double safe_acos(double v) {return acos(min(max(v, -1.), 1.));
}

        但更推荐另外一种方式:计算余弦值的过程中用long double保精度因此能严格在[-1,1]区间,这样就可以直接调用acos了(可以将下面AC代码里面的long double全部换成double再提交验证,会WA)。

AC代码

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;#define eps 1e-10
struct Point {double x, y;Point(double x = 0., double y = 0.): x(x), y(y) {}
};
typedef Point Vector;Vector operator- (const Vector& A, const Vector& B) {return Vector(A.x - B.x, A.y - B.y);
}int dcmp(double x) {return abs(x) < eps ? 0 : (x < 0. ? -1 : 1);
}bool operator== (const Point& a, const Point& b) {return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}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;
}double Lsq(const Vector& A) {return A.x*A.x + A.y*A.y;
}#define N 102
Point c[N], p[11*N]; double r[N], pi2 = M_PI + M_PI; int n; bool esc0[N], esc[11*N];double solve() {cin >> n;int a = 0, b = 0;while (n--) {char ch; cin >> ch;if (ch == 'p') {int k; cin >> k;while (k--) cin >> p[b].x >> p[b].y, esc[b++] = false;} else cin >> c[a].x >> c[a].y >> r[a], esc0[a++] = false;}for (int i=0; i<a; ++i) if (!esc0[i]) for (int j=i+1; j<a; ++j) {if (dcmp(r[i]-r[j]) <= 0 && dcmp(sqrt(Lsq(c[i]-c[j])) - r[j]+r[i]) <= 0) {esc0[i] = true; break;}if (dcmp(r[i]-r[j]) > 0 && dcmp(sqrt(Lsq(c[i]-c[j])) - r[i]+r[j]) <= 0) esc0[j] = true;}for (int i=0; i<b; ++i) if (!esc[i]) {for (int j=i+1; j<b; ++j) if (p[i] == p[j]) {esc[i] = true; break;}if (esc[i]) continue;for (int j=0; j<a; ++j) if (dcmp(sqrt(Lsq(p[i]-c[j])) - r[j]) <= 0) {esc[i] = true; break;}}for (int j=a, i=a=0; i<j; ++i) if (!esc0[i]) c[a] = c[i], r[a++] = r[i];for (int j=b, i=b=0; i<j; ++i) if (!esc[i]) p[b++] = p[i];if (a == 1 && b == 0) return pi2 * r[0];if (a == 0 && b < 2) return 0.;int s = 0; bool f = a>0;for (int i=0; i<a; ++i) if (c[i].y-r[i] < c[s].y-r[s]) s = i;for (int i=0; i<b; ++i) {if (f) {if (p[i].y < c[s].y-r[s]) s = i, f = false;} else if (p[i].y < p[s].y) s = i;}double t = 0., g = 0.; int x = s; bool u = f; Vector v(1.);while (true) {int y = -1; bool q; long double h;if (u) {for (int i=0; i<a; ++i) if (i != x) {Vector z = c[i] - c[x]; long double l = sqrt(Lsq(z)), sin = (r[i]-r[x])/l, cos = sqrt(1.-sin*sin);Vector w(z.x*cos + z.y*sin, z.y*cos - z.x*sin);cos = dcmp(Cross(v, w)) < 0 ? -2. - Dot(v, w) / l : Dot(v, w) / l;if (y < 0 || dcmp(cos-h) > 0) y = i, h = cos, q = true;}for (int i=0; i<b; ++i) {Vector z = p[i] - c[x]; long double l = sqrt(Lsq(z)), sin = r[x]/l, cos = sqrt(1.-sin*sin);Vector w(z.x*cos - z.y*sin, z.y*cos + z.x*sin);cos = dcmp(Cross(v, w)) < 0 ? -2. - Dot(v, w) / l : Dot(v, w) / l;if (y < 0 || dcmp(cos-h) > 0) y = i, h = cos, q = false;}h = h < -1. ? pi2-acos(-2.-h) : acos(h);if (f && x==s && dcmp(g + h - pi2) >= 0) return t + (pi2-g)*r[s];t += h*r[x] + (q ? sqrt(Lsq(c[y] - c[x]) - (r[y]-r[x])*(r[y]-r[x])) : sqrt(Lsq(p[y] - c[x]) - r[x]*r[x]));if (!f && !q && y==s) return t;g += h; x = y; u = q; v.x = cos(g); v.y = sin(g);} else {for (int i=0; i<a; ++i) {Vector z = c[i] - p[x]; long double l = sqrt(Lsq(z)), sin = r[i]/l, cos = sqrt(1.-sin*sin);Vector w(z.x*cos + z.y*sin, z.y*cos - z.x*sin);if (dcmp(Cross(v, w)) < 0) continue;cos = Dot(v, w) / l;if (y < 0 || dcmp(cos-h) > 0) y = i, h = cos, q = true;}for (int i=0; i<b; ++i) if (i != x) {Vector w = p[i] - p[x];if (dcmp(Cross(v, w)) < 0) continue;long double cos = Dot(v, w) / sqrt(Lsq(w));if (y < 0 || dcmp(cos-h) > 0) y = i, h = cos, q = false;}h = acos(h);t += q ? sqrt(Lsq(c[y] - p[x]) - r[y]*r[y]) : sqrt(Lsq(p[y] - p[x]));if (!f && !q && y==s) return t;g += h; x = y; u = q; v.x = cos(g); v.y = sin(g);}}return t;
}int main() {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cout << fixed << setprecision(6);int t; cin >> t;for (int kase=1; kase<=t; ++kase) cout << "Case #" << kase << ": " << solve() << endl;return 0;
}

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

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

相关文章

MySQL 核心模块揭秘 | 07 期 | 二阶段提交 (1) prepare 阶段

二阶段提交的 prepare 阶段&#xff0c;binlog 和 InnoDB 各自会有哪些动作&#xff1f; 本文基于 MySQL 8.0.32 源码&#xff0c;存储引擎为 InnoDB。 1. 二阶段提交 二阶段提交&#xff0c;顾名思义&#xff0c;包含两个阶段&#xff0c;它们是&#xff1a; prepare 阶段。…

springboot-基础-eclipse配置+helloword示例

备份笔记。所有代码都是2019年测试通过的&#xff0c;如有问题请自行搜索解决&#xff01; 下一篇&#xff1a;springboot-基础-添加model和controller的简单例子常用注解含义 目录 配置helloword示例新建项目创建文件 配置 spring boot官方有定制版eclipse&#xff0c;也就是…

BUUCTF AWD-Test1

打开靶场是这个有些简陋的界面。 随便点点&#xff0c;找到这个东西。 看到ThinkPHP&#xff0c;思路瞬间清晰&#xff0c;老熟人了。这个就是ThinkPHP漏洞。根据版本我们去找一下poc。 /index.php/?sIndex/\think\View/display&content%22%3C?%3E%3C?php%20phpinfo();…

服务端向客户端推送数据的实现方案

在日常的开发中&#xff0c;我们经常能碰见服务端需要主动推送给客户端数据的业务场景&#xff0c;比如数据大屏的实时数据&#xff0c;比如消息中心的未读消息&#xff0c;比如聊天功能等等。 本文主要介绍SSE的使用场景和如何使用SSE。 服务端向客户端推送数据的实现方案有哪…

MySQL 自增列解析(Auto_increment)

MySQL数据库为列提供了一种自增属性&#xff0c;当列被定义为自增时。Insert语句对该列即使不提供值&#xff0c;MySQL也会自动为该列生成递增的唯一标识&#xff0c;因此这个特性广泛用于主键的自动生成。 一、自增列的用法 自增列具有自动生成序列值&#xff0c;整型&#…

MYSQL04高级_逻辑架构剖析、查询缓存、解析器、优化器、执行器、存储引擎

文章目录 ①. 逻辑架构剖析②. 服务层 - 查询缓存③. 服务层 - 解析器④. 服务层 - 优化器⑤. 服务层 - 执行器⑥. MySQL8执行原理 ①. 逻辑架构剖析 ①. 服务器处理客户端请求 ②. 连接层 系统(客户端)访问MySQL服务器前,做的第一件事就是建立TCP连接经过三次握手建立连接成…

Linux使用C语言实现通过互斥锁限制对共享资源的访问

互斥锁限制共享资源的访问 主线程中有两个线程&#xff0c;分别输出信息。 #include <stdio.h> #include <pthread.h> #include <unistd.h>int g_data0;void* fun1(void *arg) {printf("t1&#xff1a;%ld thread is create\n", (unsigned long)…

稀疏图带负边的全源最短路Johnson算法

BellmanFord算法 Johnson算法解决的问题 带负权的稀疏图的全源最短路 算法流程 重新设置的每条边的权重都大于或等于0&#xff0c;跑完Djikstra后得到的全源最短路&#xff0c;记得要还原&#xff0c;即&#xff1a;f(u,v) d(u,v) - h[u] h[v] 例题

45、WEB攻防——通用漏洞PHP反序列化POP链构造魔术方法原生类

文章目录 序列化&#xff1a;将java、php等代码中的对象转化为数组或字符串等格式。代表函数serialize()&#xff0c;将一个对象转换成一个字符&#xff1b;反序列化&#xff1a;将数组或字符串等格式还成对象。代表函数unserialize()&#xff0c;将字符串还原成一个对象。 P…

MWC 2024丨Smart Health搭载高通Aware平台—美格发布智能健康看护解决方案,开启健康管理新体验

2月29日&#xff0c;在MWC 2024世界移动通信大会上&#xff0c;全球领先的无线通信模组及解决方案提供商——美格智能正式发布了新一代Cat.1模组SLM336Q&#xff0c;是中低速物联网应用场景的高性价比之选。本次还发布了首款搭载高通Aware™平台的智能看护解决方案MC303&#x…

[万字长文] 从 Vue 3 的项目模板学习 tsconfig 配置

文章目录 一、tsconfig.json 的作用二、基本介绍三、Vue 3 的 tsconfig.json 的结构分析1. 总配置 tsconfig.json2. Web 侧 tsconfig.app.jsona. 继承基础配置b. 包含和排除的文件c. 编译器选项 3. 测试 tsconfig.vitest.jsona. 继承的基础配置b. 包含和排除的文件c. 编译器选项…

OD(13)之Mermaid饼图和象限图

OD(13)之Mermaid饼图和象限图使用详解 Author: Once Day Date: 2024年2月29日 漫漫长路才刚刚开始… 全系列文章可参考专栏: Mermaid使用指南_Once_day的博客-CSDN博客 参考文章: 关于 Mermaid | Mermaid 中文网 (nodejs.cn)Mermaid | Diagramming and charting tool‍‌⁡…

FPGA-学会使用vivado中的存储器资源RAM(IP核)

问题 信号源(例如ADC)以1us一个的速率产生12位的数据现要求获得连续1ms内的数据,通过串口以115200的波特率发到电脑。 分析 数据量是1000个 数据速率不匹配 数据内容未知 数据总数据量有限 数据的使用速度低于数据的产生速度 数据生产和消耗的位宽 数据量相对较…

ywtool check命令及ywtool clean命令

一.ywtool check命令 1.1 ywtool check -I 1.2 ywtool check all 1.3 ywtool check io 1.4 ywtool check elk 1.5 ywtool check php 1.6 ywtool check mysql 1.7 ywtool check nginx 1.8 ywtool check system 1.9 ywtool check docker_nbip [容器名称] 1.10 ywtool check 1.10…

综合练习(一)

目录 列出薪金高于部门 30 的所有员工薪金的员工姓名和薪金、部门名称、部门人数 列出与 ALLEN从事相同工作的所有员工及他们的部门名称、部门人数、领导姓名 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 列出薪金高于部门 30 的所…

基于JSON的Ollama和LangChain agent

到目前为止&#xff0c;我们都可能意识到&#xff0c;通过为LLMs提供额外的工具&#xff0c;我们可以显著增强它们的功能。 例如&#xff0c;即使是ChatGPT在付费版本中也可以直接使用Bing搜索和Python解释器。OpenAI更进一步&#xff0c;为工具使用提供了经过优化的LLM模型&am…

js方法 提前结束循环

http://t.csdnimg.cn/j0gkOhttp://t.csdnimg.cn/j0gkO 一、各种循环方法如何跳出整个循环&#xff1f; 对于forEach()方法&#xff0c;目前似乎没有比较优雅的跳出整个循环的方法&#xff0c;如果你实在要用forEach()方法并且需要在某种条件下跳出整个循环提高遍历效率&#x…

政安晨:【掌握AI的深度学习工具Keras API】(二)—— 【使用内置的训练循环和评估循环】

渐进式呈现复杂性&#xff0c;是指采用一系列从简单到灵活的工作流程&#xff0c;并逐步提高复杂性。这个原则也适用于模型训练。Keras提供了训练模型的多种工作流程。这些工作流程可以很简单&#xff0c;比如在数据上调用fit()&#xff0c;也可以很高级&#xff0c;比如从头开…

uniapp实战:父子组件传参之子组件数量动态变化

需求说明 现有的设置单元列表,每个带有虚线加号的可以看做是一组设置单元,点击加号可以添加一组设置单元.点击设置单元右上角可以删除对应的设置单元. 实现思路说明 利用数组元素添加或是删除的方式实现页面数量动态变化.由于每个设置单元内容都相同所以单独封装了一个子组件.…

高效备考2025年AMC8数学竞赛:2000-2024年AMC8真题练一练

如何提高小学和初中数学成绩&#xff1f;小学和初中可以参加的数学竞赛有哪些&#xff1f;不妨了解一下AMC8美国数学竞赛&#xff0c;现在许多小学生和初中生都在参加这个比赛。如果孩子有兴趣&#xff0c;有余力的话可以系统研究AMC8的历年真题&#xff0c;即使不参加AMC8竞赛…