<题目链接>

题目大意:
给出一个四面环海的凸多边形岛屿,求出这个岛屿中的点到海的最远距离。

解题分析:

仔细思考就会发现,其实题目其实就是让我们求该凸多边形内内切圆的最大半径是多少。但是,这个最大半径,没有什么比较好的求法,于是,我们可以想到二分答案求半径。对于二分的半径,我们可以将该凸多边形的边界向内平移 r 的距离,然后再用半平面交法,用这些平移后的直线去切割原凸多边形,如果最终切得的区域不为空,则二分枚举更大的半径,反之减小枚举的半径。知道恰好围成的区域为空(或恰好不为空)为止。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std; const double eps = 1e-;
const double inf = 1e9;
const int MAXN = ;
int m;//保存多边形的点数
double r;//保存内移距离
int cCnt, curCnt;//此时cCnt为最终切割得到的多边形的顶点数、暂存顶点个数 struct point
{
double x, y;
};
point points[MAXN], p[MAXN], q[MAXN];//读入的多边形的顶点(顺时针)、p为存放最终切割得到的多边形顶点的数组、暂存核的顶点 void getline(point x, point y, double &a, double &b, double &c) //两点x、y确定一条直线a、b、c为其系数
{
a = y.y - x.y;
b = x.x - y.x;
c = y.x * x.y - x.x * y.y;
} void initial()
{
for (int i = ; i <= m; ++i)p[i] = points[i];
p[m + ] = p[];
p[] = p[m];
cCnt = m;
} point intersect(point x, point y, double a, double b, double c) //定比分点法,求两条直线的交点
{
double u = fabs(a * x.x + b * x.y + c);
double v = fabs(a * y.x + b * y.y + c);
point pt;
pt.x = (x.x * v + y.x * u) / (u + v);
pt.y = (x.y * v + y.y * u) / (u + v);
return pt;
} void cut(double a, double b, double c) //利用半平面交求出切割后多边形的所有顶点
{
curCnt = ;
for (int i = ; i <= cCnt; ++i)
{
if (a*p[i].x + b * p[i].y + c >= )q[++curCnt] = p[i]; // c因为精度问题,可能会偏小。所以有些点本应在右側而没在。
else
{
if (a*p[i - ].x + b * p[i - ].y + c > )
{
q[++curCnt] = intersect(p[i], p[i - ], a, b, c);
}
if (a*p[i + ].x + b * p[i + ].y + c > )
{
q[++curCnt] = intersect(p[i], p[i + ], a, b, c);
}
}
} for (int i = ; i <= curCnt; ++i)p[i] = q[i];
p[curCnt + ] = q[];
p[] = p[curCnt];
cCnt = curCnt;
} int dcmp(double x) //控制精度
{
if (fabs(x)<eps) return ;
else return x< ? - : ;
} void solve()
{
initial(); //初始化存放多边形顶点的p数组 for (int i = ; i <= m; ++i) { point ta, tb, tt; //得到平移后的直线
tt.x = points[i + ].y - points[i].y;
tt.y = points[i].x - points[i + ].x;
double k = r / sqrt(tt.x * tt.x + tt.y * tt.y);
tt.x = tt.x * k;
tt.y = tt.y * k;
ta.x = points[i].x + tt.x;
ta.y = points[i].y + tt.y;
tb.x = points[i + ].x + tt.x;
tb.y = points[i + ].y + tt.y; double a, b, c; //接下来用这些平移后的直线去切割原多边形
getline(ta, tb, a, b, c);
cut(a, b, c);
}
} void Reverse() { //规整化方向,逆时针变顺时针,顺时针变逆时针
for (int i = ; i < (m + ) / ; i++)
swap(points[i], points[m - i]);
} int main()
{
while (scanf("%d", &m) != EOF) {
if (m == ) break;
for (int i = ; i <= m; i++)
scanf("%lf%lf", &points[i].x, &points[i].y);
Reverse(); //由于点的顺序是逆时针输入,所以要将它改成顺时针
points[m + ] = points[]; double left = , right = inf, mid;
while ((right - left) >= eps) { //二分求半径,eps控制二分的精度
mid = (left + right) / 2.0;
r = mid; //r为内切圆半径
solve();
if (cCnt <= ) right = mid; //如果将该多边形顶点向内平移r的距离后,半平面交所得多边形为空,则说明r过大,应当适当缩小
else left = mid;
}
printf("%.6f\n", left);
}
return ;
}

2018-08-03

poj 3525 半平面交求多边形内切圆最大半径【半平面交】+【二分】的更多相关文章

  1. poj 1474 Video Surveillance - 求多边形有没有核

    /* poj 1474 Video Surveillance - 求多边形有没有核 */ #include <stdio.h> #include<math.h> const d ...

  2. POJ 3130 How I Mathematician Wonder What You Are!(半平面交求多边形的核)

    题目链接 题意 : 给你一个多边形,问你该多边形中是否存在一个点使得该点与该多边形任意一点的连线都在多边形之内. 思路 : 与3335一样,不过要注意方向变化一下. #include <stdi ...

  3. POJ 3525 Most Distant Point from the Sea (半平面交向内推进+二分半径)

    题目链接 题意 : 给你一个多边形,问你里边能够盛的下的最大的圆的半径是多少. 思路 :先二分半径r,半平面交向内推进r.模板题 #include <stdio.h> #include & ...

  4. POJ 3525 Most Distant Point from the Sea (半平面交+二分)

    Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3476   ...

  5. POJ 3525/UVA 1396 Most Distant Point from the Sea(二分+半平面交)

    Description The main land of Japan called Honshu is an island surrounded by the sea. In such an isla ...

  6. poj3675 求多边形与圆的面积交

    题意:给出多边形的顶点坐标.圆的圆心坐标和半径,求面积交 sol:又是模板题啦= = 注意poj的C++好像认不出hypot函数,要稍微改写一下. hypot(double x,double y):即 ...

  7. poj 3348 Cows 凸包 求多边形面积 计算几何 难度:0 Source:CCC207

    Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7038   Accepted: 3242 Description ...

  8. POJ 1279 Art Gallery(半平面交求多边形核的面积)

    题目链接 题意 : 求一个多边形的核的面积. 思路 : 半平面交求多边形的核,然后在求面积即可. #include <stdio.h> #include <string.h> ...

  9. POJ 3335 Rotating Scoreboard(半平面交求多边形核)

    题目链接 题意 : 给你一个多边形,问你在多边形内部是否存在这样的点,使得这个点能够看到任何在多边形边界上的点. 思路 : 半平面交求多边形内核. 半平面交资料 关于求多边形内核的算法 什么是多边形的 ...

随机推荐

  1. [HNOI2009]最小圈 (二分答案+负环)

    题面:[HNOI2009]最小圈 题目描述: 考虑带权的有向图\(G=(V,E)\)以及\(w:E\rightarrow R\),每条边\(e=(i,j)(i\neq j,i\in V,j\in V) ...

  2. centos6 python 安装 sqlite 解决 No module named ‘_sqlite3′

    原文连接: http://blog.csdn.net/jaket5219999/article/details/53512071 系统red hat6.7 也即centos6.7 python3.5. ...

  3. [转]gcc -ffunction-sections -fdata-sections -Wl,–gc-sections 参数详解

    背景 有时我们的程序会定义一些暂时使用不上的功能和函数,虽然我们不使用这些功能和函数,但它们往往会浪费我们的ROM和RAM的空间.这在使用静态库时,体现的更为严重.有时,我们只使用了静态库仅有的几个功 ...

  4. 从Nexus私服下载和上传资源(一)

    从私服中下载资源 首先要明确将资源下载到哪里 找到maven 配置文件settings.xml 文件,添加如下配置:1.添加镜像配置:将所有访问外网仓库的请求指向私服: <mirror> ...

  5. Fragment与Activity之间的相互通信

    https://blog.csdn.net/u012702547/article/details/49786417 https://blog.csdn.net/carson_ho/article/de ...

  6. 使用python中的matplotlib 画图,show后关闭窗口,继续运行命令

    使用python中的matplotlib 画图,show后关闭窗口,继续运行命令 在用python中的matplotlib 画图时,show()函数总是要放在最后,且它阻止命令继续往下运行,直到1.0 ...

  7. python中argparse模块用法实例详解

    python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...

  8. centos7版本设置OS启动默认进入图形界面还是文本界面

    相比7之前的版本,在centos7版本中,设置OS启动默认进入图形界面还是文本界面有了点变化 检查当前默认设置 [root@rems2 ~]# systemctl get-default graphi ...

  9. 巧用CASE WHEN 验证用户登录信息

    最近逛博客园的时候偶然看到一个很巧妙的SQL,巧妙利用CASE WHEN 实现一个简单的 SQL 同时验证用户帐号是否存在.密码是否正确.晓菜鸟之前的做法都是根据用户名和密码一起验证,如果验证失败直接 ...

  10. SharePoint 2013 文档库“样式”变了

    有朋友反馈说文档库的样式变了. 经查证,原来有人修改了视图的"样式":库设置—视图—样式,改为默认即可. 另外,如果编辑页面,编辑web部件的属性,在"杂项"勾 ...