zoukankan      html  css  js  c++  java
  • Pipe 计算几何基础

    题意:

    题目链接1题目链接2
    大概就是给你一些管道,求光从管口处射入最多能射多远

    思路:

    枚举拐点(上壁与下壁都算)作为直线(光束)上的两个点。然后判断这条直线和每一条线段((x_i, y_i)(x_i, y_i - 1))是否有交点。若无,则求出最远能到达的x。

    注意事项:

    丧心病狂的卡精度
    不能直接跟0比较,而应是eps(好像本来就该这样吧。。。)
    考虑精度误差,以及各种细节

    code:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N=30;
    const double eps=1e-7;
    struct point{double x,y;}e1[N],e2[N];
    inline double lfabs(double x){if(x<-eps)x=-x;return x;}
    bool operator==(point x,point y){return (lfabs(x.x-y.x)<eps)&&(lfabs(x.y-y.y)<eps);}
    point operator-(point x,point y){return (point){x.x-y.x,x.y-y.y};}
    double operator^(point x,point y){return x.x*y.y-x.y*y.x;}
    double ans;
    int n;
    inline double inc(point p1,point p2,point u,point v)
    {
    	return (((p1-u)^(p2-u))*((p1-v)^(p2-v)));//线段与直线判断交点情况
    }
    inline double slv_inc(point p1,point p2,point u,point v)
    {
    	double s1=(u-p1)^(v-p1),s2=(v-p2)^(u-p2);
    	double anss=p2.x+(p1.x-p2.x)*s2/(s1+s2);
    	return anss;
    }
    int main()
    {
    	while(7)
    	{
    		scanf("%d",&n);
    		if(!n) break;
    		for(int i=1;i<=n;++i)
    		{
    			scanf("%lf%lf",&e1[i].x,&e1[i].y);
    			e2[i]=e1[i]-(point){0.0,1.0};
    		}
    		bool pd=0;
    		int nn=n<<1;ans=e1[1].x;
    		for(int i=1;i<=nn&&(!pd);++i)
    			for(int j=i+1;j<=nn;++j)
    			{
    				point p1=i<=n?e1[i]:e2[i-n];
    				point p2=j<=n?e1[j]:e2[j-n];
    				if(p1.x>p2.x) swap(p1,p2);
    				bool flag=0;int pos=0;
    				for(int k=1;k<=n;++k)
    				{
    					if(e1[k]==p1||e1[k]==p2||e2[k]==p1||e2[k]==p2) continue;
    					if(e1[k].x-p2.x>eps){pos=k;break;}
    					if(inc(p1,p2,e1[k],e2[k])>eps){flag=1;break;}
    				}
    				if(flag) continue;
    				while(inc(p1,p2,e1[pos],e2[pos])<eps&&pos<=n)++pos;
    				if(pos>n||pos==0){puts("Through all the pipe.");pd=1;break;}
    				if(inc(p1,p2,e1[pos],e1[pos-1])<eps)ans=max(ans,slv_inc(p1,p2,e1[pos],e1[pos-1]));
    				if(inc(p1,p2,e2[pos],e2[pos-1])<eps)ans=max(ans,slv_inc(p1,p2,e2[pos],e2[pos-1]));
    			}
    		if(pd) continue;
    		printf("%.2f
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    bzoj3237 cdq分治+可撤销并查集
    bzoj2957 奥妙重重的线段树
    bzoj3718 树状数组
    bzoj3991 LCA + set
    codeforces794D dfs+图上hash
    [ZJOI2010]数字计数/烦人的数学作业
    [SCOI2009]windy数
    数位DP(学习笔记)
    UVA10559 方块消除 Blocks
    采蘑菇
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/12218608.html
Copyright © 2011-2022 走看看