JZOJ 1082. 【GDOI2005】选址
\(\text{Problem}\)
很久以前,在世界的某处有一个形状为凸多边形的小岛,岛上的居民们决定建一个祭坛,居民们任务祭坛的位置离岛的顶点处越远越好。
你的任务是求凸多边形内一点,使其与各顶点的距离中最短的距离最远,点在边上也可以。 这样的点可能有多个,你只需输出这些点与各顶点的最短距离。
\(\text{Solution}\)
非常经典的题
以答案为半径做圆,满足圆心到所有点距离大于等于半径
考虑二分半径,判断圆心存不存在
枚举任意两点,考虑分别以此半径做圆交出的点(选取内部的点,叉积判断是否在内部)
如果这点没有被所有圆覆盖,即这点到凸边形顶点的最短距离大于等于半径,说明圆心存在
算交点用相似,如果没有交点考虑其在边上交出的点一样判断
精度很神奇,不要用 \(\text{long double}\)
本地过不了数据1 \(OJ\) 上却过了?!
\(\text{Code}\)
#include <cstdio>
#include <algorithm>
#include <cmath>
#define RE register
#define IN inline
using namespace std;
const int N = 105;
const double eps = 1e-8;
double area;
int n;
struct Vector{
double x, y;
IN Vector(double xx = 0, double yy = 0){x = xx, y = yy;}
IN Vector operator - (const Vector &B){return Vector(x - B.x, y - B.y);}
IN double operator * (const Vector &B){return fabs(x * B.y - y * B.x);}
}p[N];
IN double sqr(double x){return x * x;}
IN double distance(Vector a, Vector b){return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
IN double Area(Vector a, Vector b, Vector c){return (a - b) * (c - b);}
IN double sum_Area(Vector a)
{
double res = 0;
for(RE int i = 1; i < n; i++) res += Area(a, p[i], p[i + 1]);
return res + Area(a, p[n], p[1]);
}
IN int isIn(Vector a){if (fabs(sum_Area(a) - area) <= eps) return 1; return 0;}
IN int OK(Vector a, double r)
{
double res = 1e18;
for(RE int i = 1; i <= n; i++) res = min(res, distance(a, p[i]));
return res >= r;
}
IN int check(double r)
{
for(RE int i = 1; i <= n; i++)
for(RE int j = 1; j < i; j++)
{
double d = distance(p[i], p[j]);
if (d > r * 2)
{
double k = (p[i].y - p[j].y) / (p[i].x - p[j].x), x, y;
y = min(p[i].y, p[j].y) + fabs(p[i].y - p[j].y) * r / d;
if (k > 0)
{
x = min(p[i].x, p[j].x) + fabs(p[i].x - p[j].x) * r / d;
if (OK(Vector{x, y}, r)) return 1;
x = p[i].x + p[j].x - x, y = p[i].y + p[j].y - y;
if (OK(Vector{x, y}, r)) return 1;
}
else{
x = max(p[i].x, p[j].x) - fabs(p[i].x - p[j].x) * r / d;
if (OK(Vector{x, y}, r)) return 1;
x = p[i].x + p[j].x - x, y = p[i].y + p[j].y - y;
if (OK(Vector{x, y}, r)) return 1;
}
}
else{
double w = sqrt(r * r - d * d / 4), k = w / d;
double dx = (p[i].x + p[j].x) / 2, dy = (p[i].y + p[j].y) / 2;
double x = dx - fabs(p[i].y - p[j].y) * k, y = dy + fabs(p[i].x - p[j].x) * k;
if (isIn(Vector{x, y}) && OK(Vector{x, y}, r)) return 1;
x = p[i].x + p[j].x - x, y = p[i].y + p[j].y - y;
if (isIn(Vector{x, y}) && OK(Vector{x, y}, r)) return 1;
}
}
return 0;
}
int main()
{
scanf("%d", &n);
for(RE int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
area = sum_Area(p[1]); double r = 0;
for(RE int i = 1; i <= n; i++)
for(RE int j = 1; j < i; j++) r = max(r, distance(p[i], p[j]));
double l = 0, mid = (l + r) / 2, ans;
for(RE int i = 0; i < 60; i++, mid = (l + r) / 2)
if (check(mid)) ans = mid, l = mid; else r = mid;
printf("%.3lf\n", ans);
}
JZOJ 1082. 【GDOI2005】选址的更多相关文章
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1082 线段树区间求和
codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
- 【hihoCoder】1082: 然而沼跃鱼早就看穿了一切
题目:http://hihocoder.com/problemset/problem/1082 输入一个字符串,将其中特定的单词替换成另一个单词 代码注意点: 1. getline(istre ...
- codevs 1082 线段树练习3
1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 给你N个数,有两种操作: 1: ...
- [NOIP2014] 提高组 洛谷P2038 无线网络发射器选址
题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...
- NYOJ题目1082买新书了
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsoAAAI5CAIAAAA38ougAAAgAElEQVR4nO3dPVLjStsG4G8T5CyE2A
- 【codevs】1082 线段树练习 3 <区间修改+区间和>
题目连接 http://codevs.cn/problem/1082/ Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. In ...
- 【BZOJ】1082: [SCOI2005]栅栏(二分+dfs)
http://www.lydsy.com/JudgeOnline/problem.php?id=1082 题意:n个给出木板,m个给出木板.可以将那m个木板锯成泥想要的长度.问最大能锯成多少个给出的n ...
- 基于K2 BPM的大型连锁企业开关店选址管理解决方案
业内有句名言:“门店最重要的是什么?第一是选址,第二是选址,第三还是选址” 选址是一个很复杂的综合性商业决策过程,需要定性考虑和定向分析.K2开关店&选址管理方案重点关注:如何开出更好的店?在 ...
- HDU 1082
http://acm.hdu.edu.cn/showproblem.php?pid=1082 这题开始想复杂了,error并不包括表达式本身不合法的情况 我的方法是遇到右括号就开始处理栈,如果开始最外 ...
随机推荐
- C++编程笔记(多线程学习)
目录 一.线程创建 二.线程的相关操作 2.1 join 2.2 detach 2.3 joinable 三.线程参数 3.1传参所引发的资源回收问题 3.2 将对象的成员函数作为入口函数 四.线程的 ...
- 【每日一题】【动态规划&二分】2022年2月9日-NC91 最长上升子序列(三)
描述给定数组 arr ,设长度为 n ,输出 arr 的最长上升子序列.(如果有多个答案,请输出其中 按数值(注:区别于按单个字符的ASCII码值)进行比较的 字典序最小的那个) 方法1:双层循环实现 ...
- web框架推导 wsgiref模块 jinja2模板语法 django框架简介 django基本操作
目录 纯手撸web框架 web框架的本质 手写web框架 存在的问题 基于wsgiref模块 基本介绍 推导流程 代码封装优化 总结 动静态网页 jinja2模块 前端.后端.数据库三者联动 推导流程 ...
- js 定时器(setInterval)
js 定时器 分类 编程技术 js 定时器有以下两个方法: setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式.方法会不停地调用函数,直到 clearInterval() ...
- 搭建IIS网站后,点击浏览地址,报403错误
点击左侧的浏览地址,报右侧的错误,可将目录浏览进行启用 双击进去,进行启用即可
- python中使用pip 安装第三方库报错归类及解决方式
1. 离线安装virtualenv报错,安装命令:python setup.py install 解决方式:升级setuptools 2. 安装第三方库时安装失败,安装命令:pip install ...
- 如何在 .Net 7 中将 Query 绑定到数组
在 .Net 7 中,我们可以通过绑定数组的方式来接收来自查询字符串的参数.这样就不需要再使用逗号分隔的字符串来获取参数了. 代码演示 假设我们需要从 query 上接受多个 id 并返回查询的结果. ...
- Ajax---EventLoop事件循环
前言 JavaScript 是一门单线程执行的脚本语言.也就是说,同一时间只能做一件事情. JavaScript要运行在宿主环境中(浏览器,nodejs)下.浏览器内部有执行js代码的引擎 ...
- netkit-telnet源码编译安装
介绍 Linux 下流行的 telnet 实现有两个: GNU inetutils: http://ftp.gnu.org/gnu/inetutils/ 哈佛netkit-telnet 源码包:htt ...
- MYSQL进阶学习笔记
MySQL在Linux中的使用: 1.查看mysql在linux的安装版本 mysqladmin –version 2.mysql服务的启动与停止 (1).启动: service mysql star ...