`

uva2819

阅读更多

source: http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&page=show_problem&problem=2819

 

title: Largest Empty Circle on a Segment

题目简意:给出n条线段,求圆心在线段(0, 0)-->(L,0)上 的圆在不和这些线段相交的情况下的半径的最大值。

解法: 二分是很显然的,二分圆的半径为mid,然后判断线段(0, 0)->(L, 0)到其他n条线段的 距离 在mid以内的部分,然后对这n个部分求一次并,判断求并后这部分的长度d1和线段(0, 0)-->(L, 0)的长度d2的关系,如果d1<d2,说明圆的半径还可以再大!否则则半径应该小一些。

 

#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=2005;
const double eps=1e-8;
const double teps=1e-6;
int sign(double d){
	return d<-eps ? -1 : (d > eps);
}
struct point{
	double x, y;
	point(double _x=0, double _y=0):x(_x), y(_y){}
	void set(double _x, double _y){
		x=_x;
		y=_y;
	}
	void read(){
		scanf("%lf%lf", &x, &y);
	}
	bool operator==(point p){
		return sign(x-p.x)==0 && sign(y-p.y)==0;
	}
}tps[N];
struct seg{
	point st, ed;
	void read(){
		st.read();
		ed.read();
	}
}segs[N], c;
struct cir{
	point c;
	double r;
};
int n;
bool input(){
	int l;
	scanf("%d%d", &n, &l);
	c.st.set(0, 0);
	c.ed.set(l, 0);
	int i;
	for(i=0; i<n; i++){
		segs[i].read();
	}
	return true;
}
inline double xmul(point st1, point ed1, point st2, point ed2){
	return (ed1.x - st1.x) * (ed2.y - st2.y) - (ed1.y - st1.y) * (ed2.x - st2.x);
}
point intersectPoint(point st1, point ed1, point st2, point ed2){  //求相交直线的交点
	double t = xmul(st2, st1, st2, ed2) / ((ed1.y-st1.y) * (ed2.x-st2.x) - (ed1.x-st1.x) * (ed2.y-st2.y));
	return point(st1.x+(ed1.x-st1.x)*t, st1.y+(ed1.y-st1.y)*t);
}
bool parallel(seg a, seg b){
	return sign(xmul(a.st, a.ed, b.st, b.ed))==0;
}
double dist(point a, point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool inSeg(seg a, point p){
	return sign(dist(a.st, a.ed)-dist(a.st, p)-dist(a.ed, p))==0;
}
//求点p到st->ed的垂足,列参数方程
point getRoot(point p, point st, point ed){
	point ans;
    double u=((ed.x-st.x)*(ed.x-st.x)+(ed.y-st.y)*(ed.y-st.y));
    u = ((ed.x-st.x)*(ed.x-p.x)+(ed.y-st.y)*(ed.y-p.y))/u;
    ans.x = u*st.x+(1-u)*ed.x;
    ans.y = u*st.y+(1-u)*ed.y;
    return ans;
}
double vlen(point v){
	return sqrt(v.x*v.x+v.y*v.y);
}
//P沿向量v移动len距离后的点
point tran(point p, point v, double len){
	double a=len/(vlen(v));
	return point(p.x+a*v.x, p.y+a*v.y);
}

//求线段(st, ed)在圆c里面的部分, pp存储答案,x表示近点距st的距离,
//y表示远点距st的距离,如果没有任何一部分在圆里面,则x>y
point getSeg(cir c, point st, point ed) {
	point r, cen, point, pp;
	double ll, len = dist(st, ed);
	cen=c.c;
	r = getRoot(cen, st, ed);
	ll = sqrt(c.r * c.r - (pow(cen.x - r.x, 2.0) + pow(cen.y - r.y, 2.0)));
	//ll 为半弦长
	if (dist(r, cen) <= c.r) {
		if ((st.x - r.x) * (ed.x - r.x) + (st.y - r.y) * (ed.y - r.y) <= 0) {
			pp.x = dist(st, r) - ll;
			pp.y = dist(st, r) + ll;
			if (pp.x < 0)
				pp.x = 0;
			if (pp.y > len)
				pp.y = len;
		} else {
			if (dist(st, cen) < c.r) {
				pp.x = 0;
				if (dist(ed, cen) < c.r) {
					pp.y = len;
				} else {
					pp.y = ll - dist(st, r);
				}
			} else {
				if (dist(ed, cen) < c.r) {
					pp.x = dist(st, r) - ll;
					pp.y = len;
				} else {
					pp.x = 1;
					pp.y = 0;
					return pp;
				}
			}
		}
	} else {
		pp.x = 1;
		pp.y = 0;
		return pp;
	}
	return pp;
}
//判断一个点是否完全在凸多边形里面,点是逆时针的
bool inHull(point* ps, int n, point p){
	ps[n]=ps[0];
	int i;
	for(i=0; i<n; i++){
		if(sign(xmul(ps[i], ps[i+1], ps[i], p))<=0) return false;
	}
	return true;
}
//判断一个点是否凸多边形里面(包括边上),点是逆时针的
bool inHull1(point* ps, int n, point p){
	ps[n]=ps[0];
	int i;
	seg ts;
	for(i=0; i<n; i++){
		ts.st=ps[i];
		ts.ed=ps[i+1];
		if(inSeg(ts, p)) return  true;
	}
	return inHull(ps, n, p);
	return true;
}
bool isIntersect(seg a, seg b){
	int k1, k2;
	k1=sign(xmul(a.st, a.ed, a.st,  b.st));
	k2=sign(xmul(a.st, a.ed, a.st,  b.ed));
	if(k1*k2>0 || (k1==0 && k2==0)) return false;
	k1=sign(xmul(b.st, b.ed, b.st,  a.st));
	k2=sign(xmul(b.st, b.ed, b.st,  a.ed));
	if(k1*k2>0 || (k1==0 && k2==0)) return false;
	return true;
}
bool cmp(point a, point b){
	return a.x<b.x || (sign(a.x-b.x)==0 && a.y<b.y);
}
//求线段在凸多边形ps里面的部分(完全在里面),点是逆时针的
//ans.x和ans.y分别表示这一部分到 s.st的最近 距离和最远距离
point inHull(point* ps, int n, seg s){
	ps[n]=ps[0];
	int i, size;
	seg ts;
	vector<point> vp;
	for(i=0; i<n; i++){
		ts.st=ps[i];
		ts.ed=ps[i+1];
		if(!isIntersect(s, ts)) continue;
		vp.push_back(intersectPoint(ts.st, ts.ed, s.st, s.ed));
	}
	if(inHull1(ps, n,  s.st)) vp.push_back(s.st);
	if(inHull1(ps, n,  s.ed)) vp.push_back(s.ed);
	sort(vp.begin(), vp.end(), cmp);
	point ans(1, 0);
	for(i=1, size=vp.size(); i<size; i++){
		if(vp[i-1]==vp[i]) continue;
		point tp((vp[i-1].x+vp[i].x)*0.5, (vp[i-1].y+vp[i].y)*0.5);
		if(inHull(ps, n, tp)){
			ans.x=dist(vp[i-1], s.st);
			ans.y=dist(vp[i], s.st);
			if(ans.x>ans.y){
				swap(ans.x, ans.y);
			}
		}
		break;
	}
	return ans;
}
//求线段c上的点到线段s的距离小于d的部分
//ans.x和ans.y分别表示这一部分到 c.st的最近 距离和最远距离
point getScope(seg c, seg s, double d){
	point ans, v;
	vector<point> vp;
	point rs[5];
	cir tcir;
	v.set(-(s.ed.y-s.st.y), s.ed.x-s.st.x);
	rs[3]=tran(s.st, v, d);
	rs[2]=tran(s.ed, v, d);
	v.x=-v.x;
	v.y=-v.y;
	rs[0]=tran(s.st, v, d);
	rs[1]=tran(s.ed, v, d);
	ans=inHull(rs, 4, c);
	if(ans.x<=ans.y){
		vp.push_back(ans);
	}
	tcir.r=d;
	tcir.c=s.st;
	ans=getSeg(tcir, c.st, c.ed);
	if(ans.x<=ans.y){
		vp.push_back(ans);
	}
	tcir.c=s.ed;
	ans=getSeg(tcir, c.st, c.ed);
	if(ans.x<=ans.y){
		vp.push_back(ans);
	}
	//最后肯定只会只有 一个点
	int size=vp.size();
	ans.x=1.0;
	ans.y=0.0;
	if(size>0){
		ans=vp[0];
		int i;
		for(i=1; i<size; i++){
			if(ans.x>vp[i].x){
				ans.x=vp[i].x;
			}
			if(ans.y<vp[i].y){
				ans.y=vp[i].y;
			}
		}
	}
	return ans;
}
bool check(double mid){
	int i, cnt;
	for(i=cnt=0; i<n; i++){
		tps[cnt]=getScope(c, segs[i], mid);
		if(tps[cnt].x<=tps[cnt].y){
			cnt++;
		}
	}
	if(cnt==0) return true;
	sort(tps, tps+cnt, cmp);
	double len=0;
	point p;
	for(p=tps[0], i=1; i<cnt; i++){
		if(tps[i].x>p.y){
			len+=p.y-p.x;
			p=tps[i];
		}else{
			if(p.y<tps[i].y){
				p.y=tps[i].y;
			}
		}
	}
	len += p.y-p.x;
	return sign(dist(c.st, c.ed)-len)>0;
}
void solve(){
	double l, r, mid;
	l=0;
	r=1e6;
	while(l<=r){
		mid=(l+r)*0.5;
		if(check(mid)){
			l=mid+teps;
		}else{
			r=mid-teps;
		}
	}
	double ans=l-teps;
	printf("%.3lf\n", ans);
}
int main(){
	//freopen("in.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while(t--){
		input();
		solve();
	}
	return 0;
}
 
分享到:
评论

相关推荐

    uva272 uva272 uva272

    标题中的"uva272 uva272 uva272"和描述中的"uva272"指的是UVA(University of Virginia)在线判题系统的第272题,这通常与编程竞赛和算法挑战有关。该题目的标签为"算法",意味着我们需要解决一个与计算机算法设计和...

    uvaoj 习题题目

    【uvaoj 习题题目】相关知识点详解 在编程学习和竞赛中,UVa Online Judge(简称UVa或OJ)是一个广受欢迎的在线评测系统,它为程序员提供了大量练习题目,涵盖算法、数据结构、数学等多个领域。通过解决这些题目,...

    UVA题目大全

    【UVA题目大全】是面向ACM(国际大学生程序设计竞赛)参赛者和算法爱好者的一份宝贵资源。UVA(University of Victoria Algorithm)在线判题系统是世界上最早的在线编程竞赛平台之一,它提供了大量的编程题目供用户...

    UVA_示例代码

    【UVA在线判题系统与示例代码详解】 UVA(University of Victoria Algorithm Competition)是全球知名的在线算法竞赛平台,它提供了丰富的编程题目供程序员挑战,以提高算法设计和编程能力。UVA Online Judge(简称...

    uva最全ac代码

    【标题】"uva最全ac代码" 涉及的是在编程竞赛领域中的一个集锦,特别是针对UVA(University of Victoria Algorithm)在线判题系统的解决方案。UVA是全球最早的在线算法竞赛平台之一,吸引了众多程序员参与并提交代码...

    uva 200~299 22道题解 均accept

    这些文件是针对UVA(University of Virginia)在线判题系统的编程题目的解决方案,主要涵盖了编号为200至299的题目。UVA在线判题平台是一个著名的编程竞赛和练习平台,它提供了各种难度级别的算法和编程问题,旨在...

    uva.rar_UVA_posAgent_uva 2d_uva_trilearn

    "uva.rar_UVA_posAgent_uva 2d_uva_trilearn"这个标题可能是指一个与UVA平台相关的项目或资源包,其中包含了几个特定的组件。 "posAgent"可能指的是一个定位或位置代理,这在计算机科学中通常与移动机器人、游戏或...

    Uva练习题

    【UVA练习题】是针对在线编程竞赛平台UVA(University of Virginia)的一系列练习题目。UVA是一个广受欢迎的编程竞赛网站,它为程序员提供了一个展示编程技能和解决问题的平台。这里的“不是很难,试试吧”可能意味...

    uva 50个题解

    UVA(University of Virginia)在线判题系统是一个广受欢迎的平台,汇集了众多经典算法题目。"uva 50个题解"这个资源显然是针对这个平台的题目的解答集合,特别适合对算法学习和实践感兴趣的人群。下面,我们将深入...

    uva_base_hfut_v13.2.tar.gz

    1.Uva_base的编译 在编译球队时,则需要在当前球队文件夹下打开终端输入执行以下命令(以下命令都是在root下执行的): ./configure make clean make 如果运行Uva_base后,出现球员越界或掉线的情况,就重新...

    UVaOJ-401(Palindromes).zip_401 Palindromes

    标题中的"UVaOJ-401(Palindromes)"表明这是一个关于解决UVa Online Judge(UVa OJ)上编号为401的编程挑战,该挑战的主题是"Palindromes",即回文串。回文串是指一个字符串无论从前读到后还是从后读到前都是相同的,...

    凸包 UVA109 题解

    根据给定的信息,本文将对UVA109题目的解决方案进行详细解析,重点在于理解题目背景、所需算法原理及具体实现步骤。 ### 题目背景与要求 UVA109是一道关于计算几何的经典题目,主要考察学生对于**凸包**(Convex ...

    AIML.zip_UVA_UVA 499

    标题中的"AIML.zip_UVA_UVA 499"暗示了这是一个与计算机编程相关的压缩文件,特别是针对解决UVA(University of Virginia)在线判题系统中的第499道题目。UVA在线判题系统是程序员提升算法和编程技能的一个平台,...

    UVa Online Judge部分题目代码

    UVa Online Judge是一个著名的在线编程竞赛平台,它提供了大量的算法问题供程序员们挑战,以提升他们的编程技巧和算法理解能力。这个压缩包包含了在UVa平台上部分题目的解答,是学习和参考的好资源。让我们详细了解...

    Uva 1510 - Neon Sign

    ### Uva 1510 - Neon Sign #### 问题背景与描述 在题目“Uva 1510 - Neon Sign”中,我们面对的是一个霓虹灯招牌设计问题。该霓虹灯招牌由一系列位于圆周上的角点组成,并通过发光管连接这些角点。发光管有两种...

    uva OJ 题目分类

    世界著名大学UVA OJ平台上的题目部分分类,分的不好请原谅。

    uva 部分题目解决代码

    在IT领域,特别是编程竞赛和算法训练中,UVA(University of Virginia)是一个知名的在线判题平台,它为程序员提供了大量的编程题目,旨在提升大家的算法思维和编程能力。"uva 部分题目解决代码"这个压缩包很可能是...

    uva531 LCS算法

    uva531最长公共子序列问题水题,应用简单的dp即可ac有更快速的方法欢迎讨论

    uva_base_v13.2_robocupuva_robocup2Duva_mathematicswop_platedhx_R

    标题中的"uva_base_v13.2_robocupuva_robocup2Duva_mathematicswop_platedhx_R" 提供了几个关键信息点,让我们逐一解析: 1. **uva_base**: 这可能是指UVa(University of Virginia)的基础框架或库。UVa是美国...

    算法竞赛-如何使用栈-uva357

    uva357的栈实现版本

Global site tag (gtag.js) - Google Analytics