Poj 2826 An Easy Problem?!

Posted weeping

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Poj 2826 An Easy Problem?!相关的知识,希望对你有一定的参考价值。

地址:http://poj.org/problem?id=2826

题目:

An Easy Problem?!
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 13016   Accepted: 2003

Description

It\'s raining outside. Farmer Johnson\'s bull Ben wants some rain to water his flowers. Ben nails two wooden boards on the wall of his barn. Shown in the pictures below, the two boards on the wall just look like two segments on the plane, as they have the same width. 

Your mission is to calculate how much rain these two boards can collect. 

Input

The first line contains the number of test cases. 
Each test case consists of 8 integers not exceeding 10,000 by absolute value, x1y1x2y2x3y3x4y4. (x1y1), (x2y2) are the endpoints of one board, and (x3y3), (x4y4) are the endpoints of the other one. 

Output

For each test case output a single line containing a real number with precision up to two decimal places - the amount of rain collected. 

Sample Input

2
0 1 1 0
1 0 2 1

0 1 2 1
1 0 1 2

Sample Output

1.00
0.00
思路: 这题想还是好想,考虑到以下几种情况就可以啦。

  不过这傻逼题我还是玩了一天,把discuss里的所有数据都a了后还是wa!!!

  因为求交点的模板错了!!!亏我还是从百度搜索求交点的页面的第一个网站上抄的模板!!!(坑人百度!!!)

  还好机智的我在wa了一天后发现模板有问题,换了就ac了。

  计算几何模板很重要!!!!!!!!!!!!

  很重要!!!!!!!!

  重要!!!!!!

  因为一直wa的不能自理,所以写了两种思路的ac代码(其实差不多0.0)

  1 /* 二维几何  */
  2 /* 需要包含的头文件 */
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath >
  6 #include <iostream>
  7 #include <algorithm>
  8 
  9 using namespace std;
 10 /** 常用的常量定义 **/
 11 const double INF  = 1e200;
 12 const double eps  = 1e-6;
 13 const double PI  = acos(-1.0);
 14 const int Max = 1e6;
 15 
 16 /** 基本几何结构 **/
 17 struct Point
 18 {
 19     double x,y;
 20     Point(double a=0, double b=0){x=a,y=b;}
 21     bool operator<(const Point &ta)const
 22     {
 23         if(x==ta.x)     return y<ta.y;
 24         return x<ta.x;
 25     }
 26     friend Point operator+(const Point &ta,const Point &tb)
 27     {
 28         return Point(ta.x+tb.x,ta.y+tb.y);
 29     }
 30     friend Point operator-(const Point &ta,const Point &tb)
 31     {
 32         return Point(ta.x-tb.x,ta.y-tb.y);
 33     }
 34 };
 35 struct Vec2D        ///二维向量,*重载为点乘,/重载为叉乘
 36 {
 37     double x,y;
 38     Vec2D(double ta,double tb){x=ta,y=tb;}
 39     Vec2D(Point &ta){x=ta.x,y=ta.y;}
 40     friend double operator*(const Vec2D &ta,const Vec2D &tb)
 41     {
 42         return ta.x*tb.x+ta.y*tb.y;
 43     }
 44     friend double operator/(const Vec2D &ta,const Vec2D &tb)
 45     {
 46         return ta.x*tb.y-ta.y*tb.x;
 47     }
 48     friend Vec2D operator+(const Vec2D &ta,const Vec2D &tb)
 49     {
 50         return Vec2D(ta.x+tb.x,ta.y+tb.y);
 51     }
 52     friend Vec2D operator-(const Vec2D &ta,const Vec2D &tb)
 53     {
 54         return Vec2D(ta.x-tb.x,ta.y-tb.y);
 55     }
 56     Vec2D operator=(const Vec2D &ta)
 57     {
 58         x=ta.x,y=ta.y;
 59         return *this;
 60     }
 61 };
 62 struct LineSeg      ///线段,重载了/作为叉乘运算符,*作为点乘运算符
 63 {
 64     Point s,e;
 65     LineSeg(){s=Point(0,0),e=Point(0,0);}
 66     LineSeg(Point a, Point b){s=a,e=b;}
 67     double lenth(void)
 68     {
 69         return sqrt((s.x-e.x)*(s.x-e.x)+(s.y-e.y)*(s.y-e.y));
 70     }
 71     friend double operator*(const LineSeg &ta,const LineSeg &tb)
 72     {
 73         return (ta.e.x-ta.s.x)*(tb.e.x-tb.s.x)+(ta.e.y-ta.s.y)*(tb.e.y-tb.s.y);
 74     }
 75     friend double operator/(const LineSeg &ta,const LineSeg &tb)
 76     {
 77         return (ta.e.x-ta.s.x)*(tb.e.y-tb.s.y)-(ta.e.y-ta.s.y)*(tb.e.x-tb.s.x);
 78     }
 79     LineSeg operator=(const LineSeg &ta)
 80     {
 81         s=ta.s,e=ta.e;
 82         return *this;
 83     }
 84 };
 85 struct Line         /// 直线的解析方程 a*x+b*y+c=0  为统一表示,约定 a >= 0
 86 {
 87     double a,b,c;
 88     Line(double d1=1, double d2=-1, double d3=0){ a=d1,b=d2,c=d3;}
 89 };
 90 
 91 
 92 int sgn(double ta,double tb);
 93 double getdis(const Point &ta,const Point &tb);
 94 double fArea(Point &ta,Point &tb,Point &tc);
 95 bool intersect(LineSeg &lx,LineSeg &ly);
 96 bool intersection(LineSeg &lx,LineSeg &ly,Point &pt);
 97 bool cmp(const Point &ta,const Point &tb);
 98 void graham(Point ps[],Point tb[],int n,int &num);
 99 void ConvexClosure(Point ps[],Point tb[],int n,int &num);
100 
101 
102 
103 int main(void)
104 {
105     int n;
106     double ans;
107     Point cs1,cs2;
108     LineSeg lx,ly,lz;
109     cin>>n;
110     while(n--)
111     {
112         ans=0;
113         cin>>lx.s.x>>lx.s.y>>lx.e.x>>lx.e.y;
114         cin>>ly.s.x>>ly.s.y>>ly.e.x>>ly.e.y;
115         if(lx.s.y>lx.e.y)
116             swap(lx.s,lx.e);
117         if(ly.s.y>ly.e.y)
118             swap(ly.s,ly.e);
119         //判断两条直线斜率,是否相交,是否重合或平行
120         if(sgn(lx.s.y,lx.e.y)&&sgn(ly.s.y,ly.e.y)&&intersect(lx,ly)&&intersection(lx,ly,cs1)==1)
121         {
122             lz=LineSeg(ly.e,Point(ly.e.x,1e5));
123             if(sgn(getdis(lx.e,cs1),getdis(ly.e,cs1))>=0 && intersect(lz,lx))
124             {
125                 printf("0.00\\n");
126                 continue;
127             }
128             lz=LineSeg(lx.e,Point(lx.e.x,1e5));
129             if(sgn(getdis(lx.e,cs1),getdis(ly.e,cs1))<0 && intersect(lz,ly))
130             {
131                 printf("0.00\\n");
132                 continue;
133             }
134             lz=LineSeg(Point(0,0),Point(1,0));
135             if(sgn(lz*lx/lx.lenth(),lz*ly/ly.lenth())<0)
136                 swap(lx,ly);
137             if(lx.e.y>=ly.e.y)
138             {
139                 lz=LineSeg(ly.e,Point(lx.e.x,ly.e.y));
140                 intersection(lx,lz,cs2);
141                 ans=fArea(cs1,cs2,ly.e);
142             }
143             else
144             {
145                 lz=LineSeg(lx.e,Point(ly.e.x,lx.e.y));
146                 intersection(ly,lz,cs2);
147                 ans=fArea(cs1,cs2,lx.e);
148             }
149 
150         }
151         printf("%.2f\\n",ans+eps);
152 
153     }
154 
155     return 0;
156 }
157 
158 
159 
160 
161 
162 /*******判断ta与tb的大小关系*******/
163 int sgn(double ta,double tb)
164 {
165     if(fabs(ta-tb)<eps)return 0;
166     if(ta<tb)   return -1;
167     return 1;
168 }
169 /*********求两点的距离*************/
170 double getdis(const Point &ta,const Point &tb)
171 {
172     return sqrt((ta.x-tb.x)*(ta.x-tb.x)+(ta.y-tb.y)*(ta.y-tb.y));
173 }
174 /************三角形面积**************************/
175 double fArea(Point &ta,Point &tb,Point &tc)
176 {
177     return fabs(LineSeg(ta,tb)/LineSeg(ta,tc)*0.5);
178 }
179 
180 /*********** 判断P1P2是否和P3P4相交****************************
181     其中Pi坐标为(xi,yi),需要满足两个条件:
182     (1)快速排斥试验:
183         以P1P2为对角线的矩形S1是否和以P3P4为对角线的矩形S2相交,
184         即 min(x1,x2)<=max(x3,x4) && min(x3,x4)<=max(x1,x2)
185         && min(y1,y2)<=max(y3,y4) &&min(y3,y4)<=max(y1,y2)
186     (2)跨立试验:
187         点P1,P2必然在线段P3P4的不同侧,
188         点P3,P4必然在线段P1P2的不同侧,
189 ***************************************************************/
190 bool intersect(LineSeg &lx,LineSeg &ly)
191 {
192     return     sgn(min(lx.s.x,lx.e.x),max(ly.s.x,ly.e.x))<=0
193             && sgn(min(ly.s.x,ly.e.x),max(lx.s.x,lx.e.x))<=0
194             && sgn(min(lx.s.y,lx.e.y),max(ly.s.y,ly.e.y))<=0
195             && sgn(min(ly.s.y,ly.e.y),max(lx.s.y,lx.e.y))<=0
196             && sgn((lx/LineSeg(lx.s,ly.s))*(lx/LineSeg(lx.s,ly.e)),0)<=0
197             && sgn((ly/LineSeg(ly.s,lx.s))*(ly/LineSeg(ly.s,lx.e)),0)<=0;
198 }
199 /************线段求交点**************************
200     返回-1代表直线平行,返回0代表直线重合,返回1代表线段相交
201     利用叉积求得点P分线段DC的比,
202     然后利用高中学习的定比分点坐标公式求得分点P的坐标
203 **************************************************/
204 bool intersection(LineSeg &lx,LineSeg &ly,Point &pt)
205 {
206     pt=lx.s;
207     if(sgn(lx/ly,0)==0)
208     {
209         if(sgn(LineSeg(lx.s,ly.e)/ly,0)==0)
210             return 0;//重合
211         return -1;//平行
212     }
213     double t = (LineSeg(lx.s,ly.s)/ly)/(lx/ly);
214     pt.x+=(lx.e.x-lx.s.x)*t, pt.y+=(lx.e.y-lx.s.y)*t;
215     return 1;
216 }
217 /** ************凸包算法****************
218         寻找凸包的graham 扫描法
219         PS(PointSet)为输入的点集;
220         tb为输出的凸包上的点集,按照逆时针方向排列;
221         n为PointSet中的点的数目
222         num为输出的凸包上的点的个数
223 ****************************************** **/
224 bool cmp(const Point &ta,const Point &tb)/// 选取与最后一条确定边夹角最小的点,即余弦值最大者
225 {
226 //    double tmp=LineSeg(ps[0],ta)/LineSeg(ps[0],tb);
227 //    if(sgn(tmp,0)==0)
228 //        return getdis(ps[0],ta)<getdis(ps[0],tb);
229 //    else if(tmp>0)
230 //        return 1;
231     return 0;
232 }
233 void graham(Point ps[],Point tb[],int n,int &num)
234 {
235     int cur=0,top=2;
236     for(int i=1;i<n;i++)
237         if(sgn(ps[cur].y,ps[i].y)>0 || (sgn(ps[cur].y,ps[i].y)==0 && sgn(ps[cur].x,ps[i].x)>0))
238             cur=i;
239     swap(ps[cur],ps[0]);
240     sort(ps+1,ps+n,cmp);
241     tb[0]=ps[0],tb[1]=ps[1],tb[2]=ps[2];
242     for(int i=3;i<n;i++)
243     {
244         while(sgn(LineSeg(tb[top-1],tb[top])/LineSeg(tb[top-1],ps[i]),0)<0)
245             top--;
246         tb[++top]=ps[i];
247     }
248     num=top+1;
249 }
250 /** 卷包裹法求点集凸壳,参数说明同graham算法 **/
251 void ConvexClosure(Point ps[],Point tb[],int n,int &num)
252 {
253     LineSeg lx,ly;
254     int cur,ch;
255     bool vis[Max];
256     num=-1,cur=0;
257     memset(vis,0,sizeof(vis));
258     for(int i=1;i<n;i++)
259         if(sgn(ps[cur].y,ps[i].y)>0 || (sgn(ps[cur].y,ps[i].y)==0 && sgn(ps[cur].x,ps[i].x)>0))
260             cur=i;
261     tb[++num]=ps[cur];
262     lx.s=Point(ps[cur].x-1,ps[cur].y),lx.e=ps[cur];
263     /// 选取与最后一条确定边夹角最小的点,即余弦值最大者
264     while(1)
265     {
266         double mxcross=-2,midis,tmxcross;
267         ly.s=lx.e;
268         for(int i=0;i<n;i++)if(!vis[i])
269         {
270             ly.e=ps[i];
271             tmxcross=(lx*ly)/lx.lenth()/ly.lenth();
272             if(sgn(tmxcross,mxcross)>0 ||(sgn(tmxcross,mxcross)==0 && getdis(ly.s,ly.e)<midis))
273                 mxcross=tmxcross,midis=getdis(ly.s,ly.e),ch=i;
274         }
275         if(ch==cur)break;
276         tb[++num]=ps[ch],vis[ch]=1;
277         lx.s=tb[num-1],lx.e=tb[num],ly.s=tb[num];
278     }
279 }

第二种:

  1 /* 二维几何  */
  2 /* 需要包含的头文件 */
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath >
  6 #include <iostream>
  7 #include <algorithm>
  8 
  9 using namespace std;
 10 /** 常用的常量定义 **/
 11 const double INF  = 1e200;
 12 const double eps  = 1e-6;
 13 const double PI  = acos(-1.0);
 14 const int Max = 1e6;
 15 
 16 /** 基本几何结构 **/
 17 struct Point
 18 {
 19     double x,y;
 20     Point(double a=0, double b=0){x=a,y=b;}
 21     bool operator<(const Point &ta)const
 22     {
 23         if(x==ta.x)     return y<ta.y;
 24         return x<ta.x;
 25     }
 26     friend Point operator+(const Point &ta,const Point &tb)
 27     {
 28         return Point(ta.x+tb.x,ta.y+tb.y);
 29     }
 30     friend Point operator-(const Point &ta,const Point &tb)
 31     {
 32         return Point(ta.x-tb.x,ta.y-tb.y);
 33     }
 34 };
 35 struct Vec2D        ///二维向量,*重载为点乘,/重载为叉乘
 36 {
 37     double x,y;
 38     Vec2D(double ta,double tb){x=ta,y=tb;}
 39     Vec2D(Point &ta){x=ta.x,y=ta.y;}
 40     friend double operator*(const Vec2D &ta,const Vec2D &tb)
 41     {
 42         return ta.x*tb.x+ta.y*tb.y;
 43     }
 44     friend double operator/(const Vec2D &ta,const Vec2D &tb)
 45     {
 46         return ta.x*tb.y-ta.y*tb.x;
 47     }
 48     friend Vec2D operator+(const Vec2D &ta,const Vec2D &tb)
 49     {
 50         return Vec2D(ta.x+tb.x,ta.y+tb.y);
 51     }
 52     friend Vec2D operator-(const Vec2D &ta,const Vec2D &tb)
 53     {
 54         return Vec2D(ta.x-tb.x,ta.y-tb.y);
 55     }
 56     Vec2D operator=(const Vec2D &ta)
 57     {
 58         x=ta.x,y=ta.y;
 59         return *this;
 60     }
 61 };
 62 struct LineSeg      ///线段,重载了/作为叉乘运算符,*作为点乘运算符
 63 {
 64     Point s,e;
 65     LineSeg(){s=Point(0,0),e=Point(0,0);}
 66     LineSeg(Point a, Point b){s=a,e=b;}
 67     double lenth(void)
 68     {
 69         return sqrt((s.x-e.x)*(s.x-e.x)+(s.y-e.y)*(s.y-e.y));
 70     }
 71     friend double operator*(const LineSeg &ta,const LineSeg &tb)
 72 POJ 2826  An Easy Problem!(简单数论)

POJ2826 An Easy Problem?!(线段交点,三角形面积)

poj2826 An Easy Problem?!计算几何

poj2826 An Easy Problem?! 2012-01-11

POJ 2826 An Easy Problem? 判断线段相交

POJ2826:An Easy Problem?!——题解(配特殊情况图)