SGU345 Revolution & Hdu 3684 Gunshots
来源:互联网 发布:php制作99乘法表 编辑:程序博客网 时间:2024/06/06 01:46
题目地址:
http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=10551
http://acm.hdu.edu.cn/showproblem.php?pid=3684
大意: 给你一个凸包,然后m个询问,每个询问给你一直线,求该直线将凸包分成两份中,面积最小的是多少?
这道题,自己没有做出来,可以这样来想该问题
(1)该题最关键的地方是求出与凸包的两个交点
(2)由于m很大,对于每个询问必然是log的操作。
(3)看到log,第一反应将会是二分来找这两个点,但是会发现它在整个凸包上并不满足单调性,这怎么办呢?
(4)发挥创造性,各种尝试之后,观察下图:
观察上图,你会发现 BAE和EDCB这两段上满足单调性(各点到蓝色线的有向距离是单调的)
(1)如果我们已经得到BE两点了,那么通过二分可以得到直线左边最近的点B,直线右边最近的点A,相交点即为直线BA与蓝色线的交点
(2)如何求出BE两点呢?
观察CD,DE,EA,AB,……你发现这些边一直都是往左偏,因而可以设定极角越来越大,然后你会发现E点的性质,红色线被经过E点的两条线夹住了,即极角位于两者之间,因而这里可以用二分求出B,E两点(通过两次来求这两点)
基本思路已经出来了,一些细节,请读者自己YY了,如果还有疑问,可以参考下面的代码
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int const N=50005;double eps=1e-8;double pi=acos(-1.0);struct P{ double x,y; void read(){scanf("%lf%lf",&x,&y);} P(){} P(double x,double y):x(x),y(y){} double operator *(const P& p)const{return x*p.y-y*p.x;} P operator -(const P& p)const{return P(x-p.x,y-p.y);} P operator +(const P& p)const{return P(x+p.x,y+p.y);} P operator *(double const& d)const{return P(x*d,y*d);} P operator /(double const& d)const{return P(x/d,y/d);} double angle()const{return atan2(y,x);} void out(){printf("P: %f %f\n",x,y);}};P p[N*2],Q[N];double sum[N*2];bool cmp(const P& p1,const P&p2){ if(fabs(p1.y-p2.y)<1e-8)return p1.x<p2.x; else return p1.y<p2.y;}int Poly(int n){ sort(p,p+n,cmp); int N=0; for(int i=0;i<n;i++) { while(N>=2&&(Q[N-1]-Q[N-2])*(p[i]-Q[N-1])<eps)N--; Q[N++]=p[i]; } int t=N+1; for(int i=n-2;i>=0;i--) { while(N>=t&&(Q[N-1]-Q[N-2])*(p[i]-Q[N-1])<eps)N--; Q[N++]=p[i]; } N--; for(int i=0;i<N;i++)p[i]=Q[i]; return N;}double Avg[N];int n;P u,v;int mid(double s){ if(s<0)s+=2*pi; int L=1,R=n,m; int r; while(L<=R) { m=(L+R)/2; if(Avg[m]>s+eps)R=m-1; else if(Avg[m+1]>s-eps)return m; else L=m+1; } return n;}P calc(int L,int R,double &s1,double &s2){ if(R<L)R+=n; if((u-v)*(p[L]-v)<-eps)swap(u,v); if((u-v)*(p[R]-v)> eps)swap(u,v); int s=L,e=R,m; while(s+1<e) { m=(s+e)>>1; if((u-v)*(p[m]-v)>-eps)s=m; else e=m; } s1+=sum[s]-sum[L]; s2+=sum[R]-sum[e]; P r; double t1=(p[e]-p[s])*(u-p[s]); double t2=(p[s]-p[e])*(v-p[e]); r=(u*t2+v*t1)/(t1+t2); s1+=p[s]*r; s2+=r*p[e]; return r;}double solve(){ u.read();v.read(); int k1,k2; k1=mid((u-v).angle()); k2=mid((v-u).angle()); double t1=(u-v)*(p[k1]-v); double t2=(u-v)*(p[k2]-v); if(t1*t2>-eps)return 0.0; double s1,s2; P a,b; s1=s2=0.0; a=calc(k1,k2,s1,s2); b=calc(k2,k1,s2,s1); s1+=a*b; s2+=b*a; return min(s1,s2)/2.0;}int main(){ freopen("a.in","r",stdin); int m; while(~scanf("%d",&n)) { for(int i=0;i<n;i++)p[i].read(); n=Poly(n); for(int i=0;i<n;i++) p[i+n]=p[i]; int n2=n*2; p[n2]=p[0]; for(int i=1;i<=n2;i++) { sum[i]=sum[i-1]+p[i-1]*p[i]; } for(int i=1;i<=n+1;i++) { Avg[i]=(p[i]-p[i-1]).angle(); if(Avg[i]<Avg[i-1]-eps)Avg[i]+=2*pi; } scanf("%d",&m); while(m--) printf("%.6f\n",solve()); } return 0;}
- SGU345 Revolution & Hdu 3684 Gunshots
- hdu 3684 Gunshots
- Matrix Revolution BFS HDU 1759
- HDU 1759 Matrix Revolution(BFS)
- Revolution Platform
- Slider Revolution
- [Revolution]2009-3-2
- [Revolution]2009-3-3
- [Revolution]2009-3-8
- The next revolution -- 转帖
- sgu 345-Revolution
- Lucene Revolution 2012
- 2031 - Dance Dance Revolution
- Software Industry Revolution
- poj3898 Software Industry Revolution
- The revolution of learning
- Sicily 1724. Polygon Revolution
- Slider Revolution实现幻灯片
- SQL Server 2012 Always on Availability Groups安装Step by step 3
- 外媒眼中小米的粉丝文化是怎样形成的?
- tracker-P2P服务器架设
- 做cms遇到的问题
- 字节转换
- SGU345 Revolution & Hdu 3684 Gunshots
- Python StringIO与cStringIO
- POJ 2420 A Star not a Tree?(二维费马点)
- Xms Xmx PermSize MaxPermSize 区别
- 什么是句柄?为什么会有句柄?HANDLE
- 通过句柄,获取窗口的指针
- 汉字编码问题
- oracle的sga和pga
- 无参数装饰器和有参数装饰器