hdu 4736 This Is The Job The Bear Finds(2013年成都ACM网络赛)

// Time 1718 ms; Memory 1500 K
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define eps 1e-10
#define sqr(a) ((a)*(a))
#define pi (2.0*asin(1.0))

using namespace std;

double ma[100010];

int sig(double a)
{
	return (a>eps)-(a<-eps);
}

typedef struct point
{
	double x,y;
	point(double xx=0,double yy=0):x(xx),y(yy){}
}vector;

struct node
{
	double ang,d;
	point c;
}th[10010];

point pt[10010];

bool operator < (point a,point b)
{
	return a.x<b.x || (a.x==b.x && a.y<b.y);
}
vector operator - (point a,point b)
{
	return vector(a.x-b.x,a.y-b.y);
}
point operator + (point a,vector b)
{
	return point(a.x+b.x,a.y+b.y);
}
vector operator * (vector a,double b)
{
	return vector(a.x*b,a.y*b);
}
vector operator / (vector a,double b)
{
	return vector(a.x/b,a.y/b);
}
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 len(vector a)
{
	return sqrt(sqr(a.x)+sqr(a.y));
}
double angle(vector a,vector b)
{
	double d=dot(a,b)/len(a)/len(b);
	if(sig(d-1)==0) return 0;
	if(sig(d+1)==0) return pi;
	return acos(d);
}
double dis(point a,point b,point p)
{
	return fabs(cross(b-a,p-a))/len(b-a);
}
vector rot(vector a,double b)
{
	double s=sin(b),c=cos(b);
	return vector(a.x*c-a.y*s,a.x*s+a.y*c);
}
vector rsize(vector a,double b)
{
	b/=len(a);
	return vector(a.x*b,a.y*b);
}
point bcenter(int n,double &l)
{
	point p,s;
	double tp,area=0,tpx=0,tpy=0;
	point t1=pt[0],t2=pt[0];
	p=pt[0];
	l=0;
	for(int i=1;i<=n;i++)
	{
		s.x=pt[i==n ? 0 : i].x;
		s.y=pt[i==n ? 0 : i].y;
		if(s<t1) t1=s;
		else if(t2<s) t2=s;
		l+=len(pt[i-1]-s);
		tp=cross(p,s);area+=tp/2;
		tpx+=(p.x+s.x)*tp;tpy+=(p.y+s.y)*tp;
		p.x=s.x;p.y=s.y;
	}
	if(sig(area)==0) s=(t1+t2)/2;
	else 
	{
		s.x=tpx/(6*area);s.y=tpy/(6*area);
	}
	return s;
}
point getp(point p,vector v,point cp,double r)
{
	double a=v.x,b=p.x-cp.x,c=v.y,d=p.y-cp.y;
	double e=sqr(a)+sqr(c),f=2*(a*b+c*d),g=sqr(b)+sqr(d)-sqr(r);
	double del=sqr(f)-4*e*g;
	double t=(-f+sqrt(del))/(2*e);
	return p+v*t;
}

int main()
{
	int i,j,k,u,t,n,m,cnt,my,cas=1;
	double l,sl,rad,lp,lq,ang1,ang2,ds,ll;
	point ct,ct1,ct2,g;
	vector v,w;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		my=0;
		for(i=0;i<n;i++)
		{
			scanf("%lf%lf",&pt[i].x,&pt[i].y);
			if(sig(pt[my].x-pt[i].x)>0) my=i;
		}
		scanf("%lf%lf%d",&ct.x,&ct.y,&m);
		while(sig(cross(pt[my]-ct,pt[(my-1+n)%n]-pt[my]))>0) my=(my-1+n)%n;
		g=bcenter(n,sl);                 
		v=ct-g;
		ll=len(v);
		ct1=ct;
		th[0].c=ct;
		for(j=my,k=0;k<n;k++)
		{
			u=(j+k)%n;
			lp=len(pt[u]-ct1);
			ct2=getp(pt[u],pt[(u+1)%n]-pt[u],g,ll);
			th[k+1].ang=th[k].ang+angle(ct1-g,ct2-g);      
			th[k+1].d=th[k].d+len(pt[u]-ct2)-lp;         
			th[k+1].c=ct2;
			ct1=ct2;
		}
		for(i=0;i<m;i++)
		{
			scanf("%lf",&l);
			cnt=(int)l/sl;
			l=l-cnt*sl;
			rad=cnt*2*pi;
			int right=n,left=1,mid=(n+1)/2;
			double tmp1,tmp2;
			while(left<=right)
			{
				tmp1=l-th[mid].d;
				tmp2=l-th[mid-1].d; 
				if(sig(tmp1)==0) 
				{
					mid++;break;
				}
				if(sig(tmp2)==0) break;
				if(sig(tmp1)<0 && sig(tmp2)>0) 
					break;
				if(sig(tmp1)>0) left=mid+1;
				else right=mid-1;
				mid=(left+right)/2;
			}
			j=mid;   
			if(left>right) j++;
			rad+=th[j-1].ang;
			l-=th[j-1].d;        
			if(sig(l)>0)
			{
				u=(my+j-1)%n;
				lp=len(pt[u]-g);
				lq=len(th[j-1].c-pt[u])+l;
				ang1=acos((sqr(lp)+sqr(ll)-sqr(lq))/(2*lp*ll));
				ang2=ang1-angle(pt[u]-g,th[j-1].c-g);
				rad+=ang2;          
			}
			ma[i]=rad/pi*180;
		}
		printf("Case #%d:\n",cas++);
		for(i=0;i<m;i++) 
			printf("%.3lf\n",ma[i]);
	}
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值