POJ 3525 二分+半平面交

Most Distant Point from the Sea

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 3812   Accepted: 1779   Special Judge

Description

The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it is natural to ask a question: “Where is the most distant point from the sea?” The answer to this question for Honshu was found in 1996. The most distant point
is located in former Usuda Town, Nagano Prefecture, whose distance from the sea is 114.86 km.

In this problem, you are asked to write a program which, given a map of an island, finds the most distant point from the sea in the island, and reports its distance from the sea. In order to simplify the problem, we only consider maps representable by convex
polygons.

Input

The input consists of multiple datasets. Each dataset represents a map of an island, which is a convex polygon. The format of a dataset is as follows.

n    
x1   y1
  ?  
xn   yn

Every input item in a dataset is a non-negative integer. Two input items in a line are separated by a space.

n in the first line is the number of vertices of the polygon, satisfying 3 ≤
n ≤ 100. Subsequent n lines are the x- and y-coordinates of the
n vertices. Line segments (xi, yi)–(xi+1,
yi+1) (1 ≤ in ? 1) and the line segment (xn,
yn)–(x1, y1) form the border of the polygon in counterclockwise order. That is, these line segments see the inside of the polygon in the left of their directions. All coordinate values are between
0 and 10000, inclusive.

You can assume that the polygon is simple, that is, its border never crosses or touches itself. As stated above, the given polygon is always a convex one.

The last dataset is followed by a line containing a single zero.

Output

For each dataset in the input, one line containing the distance of the most distant point from the sea should be output. An output line should not contain extra characters such as spaces. The answer should not have an error greater than 0.00001 (10?5).
You may output any number of digits after the decimal point, provided that the above accuracy condition is satisfied.

Sample Input

4
0 0
10000 0
10000 10000
0 10000
3
0 0
10000 0
7000 1000
6
0 40
100 20
250 40
250 70
100 90
0 70
3
0 0
10000 10000
5000 5001
0

Sample Output

5000.000000
494.233641
34.542948
0.353553

在大海的中央,给定一个n边凸多边形的岛,求岛上距离大海最远的点,输出它到大海的距离。

二分距离,然后把多边形向内部收缩,判断半平面是否存在。

代码:

/* ***********************************************
Author :_rabbit
Created Time :2014/5/4 15:03:55
File Name :20.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 10000000
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
int dcmp(double x){
	if(fabs(x)<eps)return 0;
	return x>0?1:-1;
}
struct Point{
	double x,y;
	Point(double _x=0,double _y=0){
		x=_x;y=_y;
	}
};
Point operator + (const Point &a,const Point &b){
	return Point(a.x+b.x,a.y+b.y);
}
Point operator - (const Point &a,const Point &b){
	return Point(a.x-b.x,a.y-b.y);
}
Point operator * (const Point &a,const double &p){
	return Point(a.x*p,a.y*p);
}
Point operator / (const Point &a,const double &p){
	return Point(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);
}
bool operator == (const Point &a,const Point &b){
	return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Point  a,Point b){
	return a.x*b.x+a.y*b.y;
}
double Length(Point a){
	return sqrt(Dot(a,a));
}
double Angle(Point a,Point b){
	return acos(Dot(a,b)/Length(a)/Length(b));
}
double angle(Point a){
	return atan2(a.y,a.x);
}
double Cross(Point a,Point b){
	return a.x*b.y-a.y*b.x;
}
Point vecunit(Point a){
	return a/Length(a);
}
Point Normal(Point a){
	return Point(-a.y,a.x)/Length(a);
}
Point Rotate(Point a,double rad){
	return Point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
double Area2(Point a,Point b,Point c){
	return Length(Cross(b-a,c-a));
}
struct Line{
	Point p,v;
	double ang;
	Line(){};
	Line(Point p,Point 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 dcmp(Cross(L.v,p-L.p))>=0;
}
Point GetLineIntersection(Point p,Point v,Point q,Point w){
	Point u=p-q;
	double t=Cross(w,u)/Cross(v,w);
	return p+v*t;
}
Point GetLineIntersection(Line a,Line b){
	return GetLineIntersection(a.p,a.v,b.p,b.v);
}
vector<Point> HPI(vector<Line> L){
	int n=L.size();
	sort(L.begin(),L.end());//将所有半平面按照极角排序。
	/*for(int i=0;i<n;i++){
		cout<<"han  "<<i<<" ";
		printf("%.2lf  %.2lf  %.2lf  %.2lf  %.2lf\n",L[i].p.x,L[i].p.y,L[i].v.x,L[i].v.y,L[i].ang);
	}*/
	int first,last;
	vector<Point> p(n);
	vector<Line> q(n);
	vector<Point> ans;
	q[first=last=0]=L[0];
	for(int i=1;i<n;i++){
		while(first<last&&!OnLeft(L[i],p[last-1]))last--;//删除顶部的半平面
		while(first<last&&!OnLeft(L[i],p[first]))first++;//删除底部的半平面
		q[++last]=L[i];//将当前的半平面假如双端队列顶部。
		if(fabs(Cross(q[last].v,q[last-1].v))<eps){//对于极角相同的,选择性保留一个。
			last--;
			if(OnLeft(q[last],L[i].p))q[last]=L[i];
		}
		if(first<last)p[last-1]=GetLineIntersection(q[last-1],q[last]);//计算队列顶部半平面交点。
	}
	while(first<last&&!OnLeft(q[first],p[last-1]))last--;//删除队列顶部的无用半平面。
	if(last-first<=1)return ans;//半平面退化
	p[last]=GetLineIntersection(q[last],q[first]);//计算队列顶部与首部的交点。
	for(int i=first;i<=last;i++)ans.push_back(p[i]);//将队列中的点复制。
	return ans;
}
double PolyArea(vector<Point> p){
	int n=p.size();
	double ans=0;
	for(int i=1;i<n-1;i++)
		ans+=Cross(p[i]-p[0],p[i+1]-p[0]);
	return fabs(ans)/2;
}
Point pp[200],v[200],v2[200];
int main()
{
     //freopen("data.in","r",stdin);
     //freopen("data.out","w",stdout);
     int n;
	 int cc=0;
	 while(~scanf("%d",&n)&&n){
		for(int i=0;i<n;i++)scanf("%lf%lf",&pp[i].x,&pp[i].y);
	    for(int i=0;i<n;i++){
			v[i]=pp[(i+1)%n]-pp[i];
			v2[i]=Normal(v[i]);
		}
		double left=0,right=20000;
		while(right-left>1e-6){
			vector<Line> L;
			double mid=(left+right)/2;
			for(int i=0;i<n;i++)
				L.push_back(Line(pp[i]+v2[i]*mid,v[i]));
			vector<Point> ans=HPI(L);
			if(!ans.size())right=mid;
			else left=mid;
			//cout<<"han "<<ans.size()<<" "<<mid<<endl;
		}
		printf("%.6lf\n",left);
	 }
     return 0;
}

POJ 3525 二分+半平面交

时间: 2024-07-29 06:55:33

POJ 3525 二分+半平面交的相关文章

POJ 3525 Most Distant Point from the Sea 二分+半平面交

题目大意:给出一个岛的海岸线的轮廓,求这个岛上的所有点到海岸的最长距离是多少. 思路:求多边形内切圆的问题要用二分+半平面交解决.二分半径的长度,然后将所有的边向左侧移动这个二分的长度,然后利用半平面交来判断是否能够满足条件.如果满足条件就提高下界,否则减小上界. 我的移动的方法是这样的,首先每条边都要用点向量式来表示,就是边上任意一点和这条边的方向向量.这样做以后的操作会方便很多.然后将每个直线的向左的法向量求出来(比如l的向量是v(x,y),那么它向左侧的法向量是(-y,x)),然后将法向量

【bzoj2732】[HNOI2012]射箭 二分+半平面交

题目描述 沫沫最近在玩一个二维的射箭游戏,如下图 1 所示,这个游戏中的 x 轴在地面,第一象限中有一些竖直线段作为靶子,任意两个靶子都没有公共部分,也不会接触坐标轴.沫沫控制一个位于(0,0)的弓箭手,可以朝 0 至 90?中的任意角度(不包括 0度和 90度),以任意大小的力量射出带有穿透能力的光之箭.由于游戏中没有空气阻力,并且光之箭没有箭身,箭的轨迹会是一条标准的抛物线,被轨迹穿过的所有靶子都认为被沫沫射中了,包括那些 只有端点被射中的靶子.这个游戏有多种模式,其中沫沫最喜欢的是闯关模式

How I Mathematician Wonder What You Are! POJ - 3130(半平面交,多边形内核)

How I Mathematician Wonder What You Are! POJ - 3130 题意:判断多边形是否有内核 思路:半平面交题,逆时针存入 1 // 2 // Created by HJYL on 2020/2/6. 3 // 4 #include<iostream> 5 #include<stdio.h> 6 #include<algorithm> 7 #include<math.h> 8 using namespace std; 9

BZOJ 3800 Saber VS Lancer/POJ 1755 Triathlon 半平面交

题目大意:有n个人进行铁人三项比赛,对于这三种运动,每个人都有一个固定的速度,但是每种运动的长度是多少并不知道.现在问裁判可不可以通过调整这三项运动的长度来使某一个人赢得比赛. 思路:考虑现在我们想让一个人赢的时候,这个人的三个速度分别为v1,v2,v3,想让所有人都输给他,设某一个人的三个速度是v1',v2',v3'.设三项的比赛的长度为l1,l2,l3.那么不难得到如下方程:l1 / v1 + l2 / v2 + l3 / v3 < l1 / v1' + l2 / v2' + l3 / v3

POJ 2451 Uyuw&#39;s Concert(半平面交nlgn)

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring> #include <cmath> #include <stack> #include <queue> #include <vector> #include <

计算几何 半平面交

LA 4992 && hdu 3761 Jungle Outpost 杭电的有点坑啊..一直爆内存,后来发现大白的半平面交模板那里 point *p = new point[n]; line *q = new line[n]这里出了问题,应该是在函数里面申请不了比较大的数组,所以爆内存..我在全局定义了两个数组就不会爆了.. 本来跑了17s多的,后来半平面交sort( l, l + n ) 被我注释了,就跑了9s多,LA上跑了 2s..应该是输入数据比较好,不用按照极角排序..然后就是照着

POJ3525 半平面交

题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似二元函数的线性规划.如图 求半平面交:用的kuangbin模板= = sol:二分答案 二分距离值,按这个值把边界向内缩,再求新的半平面交.如图: 绿色的是原图形,蓝色是按距离值向里面缩进去之后得到的新图形.对这个新图做半平面交即可. 若半平面交存在,说明与边界的距离是该值的点存在(半平面交里面的点

HDU 2297 半平面交

Run Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 640    Accepted Submission(s): 181 Problem Description Since members of Wuhan University ACM Team are lack of exercise, they plan to particip

关于半平面交

嗯,这是一个很屌的东西.可以把他想象成数学中的线性规划问题,然后自然而然得想到就可以求最优解啦. 如何求解半平面交????? 做法一:暴力枚举点,用该点切割现有的凸多边形,这样的复杂度是O(n^2) 做法二:神奇的分治O(nlogn),然而我并不会.... 做法三:参见2006年朱泽园大神发明的排序增量法:这里就暂时不给详细介绍了. 复杂度O(nlogn),如果把快速排序改成基数排序,复杂度可以进一步降为:O(n)!!!!!! 半平面交的另外一个应用是求多边形的核:可以想象成站在一个多边形的点上