题意:

给出一个凸n边形,求多边形内部一点使得该点到边的最小距离最大。

分析:

最小值最大可以用二分。

多边形每条边的左边是一个半平面,将这n个半平面向左移动距离x,则将这个凸多边形缩小了。如果这n个半平面交非空,则存在这样距离为x的点,反之则不存在。

半平面交的代码还没有完全理解。

和凸包类似,先对这些半平面进行极角排序。每次新加入的平面可能让队尾的平面变得“无用”,从而需要删除。由于极角序是环形的,所以也可能让队首元素变得“无用”。所以用双端队列来维护。

 //#define LOCAL
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std; const double eps = 1e-; struct Point
{
double x, y;
Point(double x=, double y=):x(x), y(y){}
};
typedef Point Vector;
Point operator + (Point A, Point B) { return Point(A.x+B.x, A.y+B.y); }
Point operator - (Point A, Point B) { return Point(A.x-B.x, A.y-B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
double Length(Vector A) { return sqrt(Dot(A, A)); }
Vector Normal(Vector A) { double l = Length(A); return Vector(-A.y/l, A.x/l); } double PolygonArea(const vector<Point>& p)
{
double ans = 0.0;
int n = p.size();
for(int i = ; i < n-; ++i)
ans += Cross(p[i]-p[], p[i+]-p[]);
return ans/;
} struct Line
{
Point p;
Vector v;
double ang;
Line() {}
Line(Point p, Vector v):p(p), v(v) { ang = atan2(v.y, v.x); }
bool operator < (const Line& L) const
{
return ang < L.ang;
}
}; bool OnLeft(const Line& L, const Point& p)
{ return Cross(L.v, p-L.p) > ; } Point GetLineIntersection(const Line& a, const Line& b)
{
Vector u = a.p-b.p;
double t = Cross(b.v, u) / Cross(a.v, b.v);
return a.p + a.v*t;
} vector<Point> HalfplaneIntersection(vector<Line> L)
{
int n = L.size();
sort(L.begin(), L.end()); int first, last;
vector<Point> p(n);
vector<Line> q(n);
vector<Point> ans; q[first=last=] = L[];
for(int i = ; i < n; ++i)
{
while(first < last && !OnLeft(L[i], p[last-])) last--;
while(first < last && !OnLeft(L[i], p[first])) first++;
q[++last] = L[i];
if(fabs(Cross(q[last].v, q[last-].v)) < eps) //Èç¹ûÁ½Ö±Ï߯½ÐУ¬È¡ÄÚ²àµÄÄǸö
{
last--;
if(OnLeft(q[last], L[i].p)) q[last] = L[i];
}
if(first < last) p[last-] = GetLineIntersection(q[last-], q[last]);
}
while(first < last && !OnLeft(q[first], p[last-])) last--;
if(last - first <= ) return ans;
p[last] = GetLineIntersection(q[last], q[first]); for(int i = first; i <= last; ++i) ans.push_back(p[i]);
return ans;
} int main(void)
{
#ifdef LOCAL
freopen("3890in.txt", "r", stdin);
#endif int n;
while(scanf("%d", &n) == && n)
{
vector<Point> p, v, normal;
int m, x, y;
for(int i = ; i < n; ++i) { scanf("%d%d", &x, &y); p.push_back(Point(x, y)); }
if(PolygonArea(p) < ) reverse(p.begin(), p.end()); for(int i = ; i < n; ++i)
{
v.push_back(p[(i+)%n] - p[i]);
normal.push_back(Normal(v[i]));
} double left = , right = ;
while(right - left > 5e-)
{
vector<Line> L;
double mid = (right + left) / ;
for(int i = ; i < n; ++i) L.push_back(Line(p[i] + normal[i]*mid, v[i]));
vector<Point> Poly = HalfplaneIntersection(L);
if(Poly.empty()) right = mid;
else left = mid;
}
printf("%.6lf\n", left);
} return ;
}

代码君

LA 3890 (半平面交) Most Distant Point from the Sea的更多相关文章

  1. LA 2218 (半平面交) Triathlon

    题意: 有n个选手,铁人三项有连续的三段,对于每段场地选手i分别以vi, ui 和 wi匀速通过. 对于每个选手,问能否通过调整每种赛道的长度使得他成为冠军(不能并列). 分析: 粗一看,这不像一道计 ...

  2. LA 3890 Most Distant Point from the Sea(半平面交)

    Most Distant Point from the Sea [题目链接]Most Distant Point from the Sea [题目类型]半平面交 &题解: 蓝书279 二分答案 ...

  3. 简单几何(半平面交+二分) LA 3890 Most Distant Point from the Sea

    题目传送门 题意:凸多边形的小岛在海里,问岛上的点到海最远的距离. 分析:训练指南P279,二分答案,然后整个多边形往内部收缩,如果半平面交非空,那么这些点构成半平面,存在满足的点. /******* ...

  4. UVA 3890 Most Distant Point from the Sea(二分法+半平面交)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11358 [思路] 二分法+半平面交 二分与海边的的距离,由法向量可 ...

  5. POJ 3525 Most Distant Point from the Sea [半平面交 二分]

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

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

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

  7. 【POJ 3525】Most Distant Point from the Sea(直线平移、半平面交)

    按逆时针顺序给出n个点,求它们组成的多边形的最大内切圆半径. 二分这个半径,将所有直线向多边形中心平移r距离,如果半平面交不存在那么r大了,否则r小了. 平移直线就是对于向量ab,因为是逆时针的,向中 ...

  8. poj3525Most Distant Point from the Sea(半平面交)

    链接 求凸多边形内一点距离边最远. 做法:二分+半平面交判定. 二分距离,每次让每条边向内推进d,用半平面交判定一下是否有核. 本想自己写一个向内推进..仔细一看发现自己的平面交模板上自带.. #in ...

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

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

随机推荐

  1. 3240: [Noi2013]矩阵游戏

    Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的 ...

  2. ffmpeg mp3转ogg的命令

    ffmpeg.exe -y -i bb.mp3 -acodec libvorbis -ab 128k bb.ogg

  3. vim分屏快捷键使用/增大/减小字体使用

    问题描述: vim分屏快捷键使用 问题解决:         (1)vim 分屏快捷键           (2)vim高度改变          (3)vim中增加和减少字体大小  使用快捷键Ctr ...

  4. oracle将两个结果连接后进行查询,得到两个查询的联合结果

    一.需求 用户答题,共3道,必须3题都答完才能提交. 目的:要查询用户答对了几题,答错了几题.(当然此处可以只查答对的题目数,用3减即得答错题的题目数) 二.sql select * ) rightC ...

  5. ssh-add 报错 Could not open a connection to your authentication agent

    ERROR: [root@testcentos01 ~]# ssh-add Could not open a connection to your authentication agent 在shel ...

  6. UNIX command Questions Answers asked in Interview

    UNIX or Linux operating system has become default Server operating system and for whichever programm ...

  7. C#的cs文件中Response.Clear();Response.ClearHeaders()的作用

    在学习一个CS文件,如下:public partial class GetPic : System.Web.UI.Page{    protected void Page_Load(object se ...

  8. 【转载】Eclipse自动编译问题

    今天调试的时候发现问题:调试的时候竟然在我注释的里面走,当时那个郁闷啊,每次都要clean下才可以,晚上感觉不对劲,上网查了查,原来是bulid automatically这个我把勾去掉了,下面是原文 ...

  9. QAQ数论模板笔记√

    #include <cstdio> using namespace std; long long gcd(long long a, long long b) { // (a, b) ret ...

  10. 李洪强iOS之Foundation框架—字符串

    Foundation框架—字符串 一.Foundation框架中一些常用的类 字符串型: NSString:不可变字符串 NSMutableString:可变字符串 集合型: 1) NSArray:O ...