HDU 4454 杭州赛区现场赛B题

就是三分~囧~现场赛时把三分的下界写错了一直到最后也没过~另外还把切点都求错了~没救了没救了~刚才看到终于把题挂出来速度去重写~然后1Y~啧啧啧~

做法就是求蚂蚁所在的点与圆形成的两个切线,两个切点把圆绵分成两部分,则蚂蚁爬到圆上的那一点一定在 圆心角<PI 的那一半圆弧上【下图红色部分】:


在红色圆弧上取一个点求点到起点的距离和点到矩形的距离和,则在这段圆弧上的距离和一定是凹函数,我是选择三分角度求圆弧上的点。

当天现场赛结束时芒果神给我说了一个三分矩形上的点然后二分的方法~苣蒻表示没听懂QAQ

现场没能写出这题各种悲剧QAQ滚来滚去滚来滚去

另外现场赛好多人用枚举角度过了这个题QAQ不科学QAQ【扔桌子~摔

刚才膜拜到另一种三分方法,把圆周分成两部分(0,PI)和(PI,2*PI)然后分别三分,这样就不用求切点了QAQ【2012/11/08 20:20】

刚才和别人讨论了一下这题的证明,忽然觉得好麻烦【虽然证出来了】…我当时是靠直觉【2013年6月12日23:04:49】

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
using namespace std;
#define PI acos(-1)
#define INF 1<<30
#define EPS 1e-6
#define SET(a,b) memset(a,b,sizeof(a))
#define N 10010
#define M 10010
struct point
{
	double x,y;
	int init(){scanf("%lf %lf",&x,&y);}
}cir,p[5],a,o,q1,q2;
double r,th1,th2;
inline double xmult(point p0,point p1,point p2)
{
	return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
point rotate(point p,double angle)
{
	point res;
	res.x=p.x*cos(angle)-p.y*sin(angle);
	res.y=p.x*sin(angle)+p.y*cos(angle);
	return res;
}
void TPC(point poi,point o,double r,point &r1,point &r2)
{
	double line=sqrt((poi.x-o.x)*(poi.x-o.x)+(poi.y-o.y)*(poi.y-o.y));
	double angle=acos(r/line);
	point unit,lin;
	lin.x=poi.x-o.x;
	lin.y=poi.y-o.y;
	unit.x=lin.x/sqrt(lin.x*lin.x+lin.y*lin.y)*r;
	unit.y=lin.y/sqrt(lin.x*lin.x+lin.y*lin.y)*r;
	r1=rotate(unit,-angle);
	r2=rotate(unit,angle);
	r1.x+=o.x; r1.y+=o.y;
	r2.x+=o.x; r2.y+=o.y;
}
double dist(point a,point b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
point intersect(point u1,point u2,point v1,point v2)
{
	double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
			/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
	point ret=u1;
	ret.x+=(u2.x-u1.x)*t;
	ret.y+=(u2.y-u1.y)*t;
	return ret;
}
double ptoseg(point p,point l1,point l2)
{
	point t=p;
	t.x+=l1.y-l2.y;
	t.y+=l2.x-l1.x;
	if(xmult(p,l1,t)*xmult(p,l2,t)>EPS)
		return min(dist(p,l1),dist(p,l2));
	return dist(intersect(p,t,l1,l2),p);
}
double ddd(double angle)
{
	point ret;
	ret.x=cir.x+r*cos(angle);
	ret.y=cir.y+r*sin(angle);
	double ans=1e100;
	for(int i=0;i<4;i++)
		ans=min(ans,ptoseg(ret,p[i],p[i+1]));
	return dist(ret,a)+ans;
}
void sf(double l,double r)
{
	double m1,m2;
	while (fabs(r-l)>EPS)
	{
		m1=l+(r-l)/3;
		m2=l+(r-l)/3*2;
		if(ddd(m1)<ddd(m2)) r=m2;
		else l=m1;
	}
	printf("%.2lf\n",ddd(l));
}
int main()
{
	while (a.init())
	{
		if(a.x==0 && a.y==0) break;
		cir.init(); scanf("%lf",&r);
		p[0].init(); p[2].init();
		p[1].x=p[2].x; p[1].y=p[0].y;
		p[3].x=p[0].x; p[3].y=p[2].y;
		p[4]=p[0];
		TPC(a,cir,r,q1,q2);
		th1=atan2(q1.y-cir.y,q1.x-cir.x);
		th2=atan2(q2.y-cir.y,q2.x-cir.x);
		if(th1<0) th1+=2*PI;
		if(th2<0) th2+=2*PI;
		if(th1>th2) swap(th1,th2);
		if(th2-th1<PI) sf(th1,th2);
		else sf(th2-2*PI,th1);
	}
	
	return 0;
}










            
阅读更多

没有更多推荐了,返回首页