| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
再附上我的渣渣AC代码#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
//#define eps le-8
const double eps=1e-8;
const double INF=9999999;
const double inf=7777777;
using namespace std;
typedef struct Node
{
double x;
double y;
}point;
point p[4];
int sign(double x)
{
return (x>eps)-(x<-eps);
}
double Distance(point p1,point p2)// 返回两点之间欧氏距离
{
return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );
}
double xmult(point p0,point p1,point p2)//叉积
{
//cout<<p0.x<<" "<<p0.y<<" "<<p1.x<<" "<<p1.y<<" "<<p2.x<<" "<<p2.y<<endl;
double p=(p1.x-p0.x)*(p2.y-p0.y);//WA20多次输出无数次中间结果才发现叉积直接返回会出问题(会出现莫名其妙的值),不信可以拿样例六测试下,会发现当你判断有没有交点直接返回没有,其实是有(2,2)这个交点
double q=-(p2.x-p0.x)*(p1.y-p0.y);//建议以后叉积都这样写(不会损失精度,因为你返回的值也是double)
return p+q;
}
//相交返回true,否则为false,接口为两线段的端点
bool IsIntersected(point s1,point e1,point s2,point e2)//判断是否相交
{
return (max(s1.x,e1.x)>=min(s2.x,e2.x))&& (max(s2.x,e2.x)>=min(s1.x,e1.x))&&(max(s1.y,e1.y)>=min(s2.y,e2.y))&&(max(s2.y,e2.y)>=min(s1.y,e1.y))&&(sign(xmult(s1,s2,e1))*sign(xmult(s1,e1,e2))>=0)&&(sign(xmult(s2,s1,e2))*sign(xmult(s2,e2,e1))>=0);
}
//计算两直线交点,注意事先判断直线是否平行!
//线段交点请另外判线段相交(同时还是要判断是否平行!)
point Intersection(point u1,point u2,point v1,point v2)//如果相交返回交点
{
point res=u1;
double a=(u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x);
double b=(u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x);
if(sign(b)==0)//这里要特判下,如果除数是0,证明两条线段斜率一样并且至少重合一个公共点
{
res.x==INF;
res.y==INF;
}
else
{
double t=a/b;
res.x+=(u2.x-u1.x)*t;
res.y+=(u2.y-u1.y)*t;
}
return res;
}
bool Same(point u1,point u2,point v1,point v2)//如果是同一条线段
{
if((sign(u1.y-u2.y)==0)&&(sign(u1.y-v1.y)==0)&&(sign(v1.y-v2.y)==0))
{
return true;
}
return false;
}
bool Vertical(point u1,point u2,point v1,point v2)//如果有一条线段垂直,只要另一条线段平行X轴就是0
{
if(sign(u1.y-u2.y)==0)
{
if(sign(v1.x-v2.x)==0)
return true;
}
else if(sign(v1.y-v2.y)==0)
{
if(sign(u1.x-u2.x)==0)
return true;
}
return false;
}
bool Parallel(point u1,point u2,point v1,point v2)//其实坐到后面发现,两条线段任意一条平行X轴都是0
{
if((sign(u1.y-u2.y)==0)||(sign(v1.y-v2.y)==0))
return true;
return false;
}
double slope(point u,point v)//斜率
{
if((sign(v.x-u.x)==0)&&(sign(v.y-u.y)==0))//如果交点和最上面的点重合那么就0了
{
return INF;
}
if(sign(v.x-u.x)==0)
{
return inf;
}
return (v.y-u.y)/(v.x-u.x);
}
int main()
{
int T;
int n,m,i,j;
int num1,num2;
point u1,u2,v1,v2;
double d1,d2,k1,k2,h,l,K,B;
double area,maxn1,maxn2;
point res,a,b,c;
cin>>T;
while(T--)
{
cin>>u1.x>>u1.y>>u2.x>>u2.y;
cin>>v1.x>>v1.y>>v2.x>>v2.y;
p[0]=u1;
p[1]=u2;
p[2]=v1;
p[3]=v2;
h=0;
l=0;
area=0;
maxn1=-99999;
maxn2=-99999;
if(IsIntersected(u1,u2,v1,v2))//是否相交
{
if(Same(u1,u2,v1,v2))
{
//cout<<"00"<<endl;
cout<<"0.00"<<endl;
continue;
}
if(Vertical(u1,u2,v1,v2))
{
//cout<<"22"<<endl;
cout<<"0.00"<<endl;
continue;
}
if(Parallel(u1,u2,v1,v2))
{
//cout<<"33"<<endl;
cout<<"0.00"<<endl;
continue;
}
if(sign(slope(u1,u2)-slope(v1,v2))==0)
{
//cout<<"44"<<endl;
cout<<"0.00"<<endl;
continue;
}
res=Intersection(u1,u2,v1,v2);
//cout<<"OK!"<<endl;
if(res.x==INF&&res.y==INF)
{
//cout<<"55"<<endl;
cout<<"0.00"<<endl;
continue;
}
//cout<<d1<<" "<<d2<<" "<<d3<<" "<<d4<<endl;
for(i=0;i<4;i++)
{
if(maxn1<p[i].y)
{
maxn1=p[i].y;
num1=i;
}
}
for(i=0;i<4;i++)
{
if(i!=num1)
{
if(maxn2<p[i].y)
{
maxn2=p[i].y;
num2=i;
}
}
}
a.x=p[num1].x;
a.y=p[num1].y;
b.x=p[num2].x;
b.y=p[num2].y;
d1=Distance(a,res);
d2=Distance(b,res);
if((sign(d1-d2)==-1)&&(sign(a.y-b.y)==0))//这里是判断哪条是最上面的点所在的那条直线
swap(a,b);
//if((sign(a.x-res.x)==0))
//cout<<a.x<<" "<<a.y<<" "<<b.x<<" "<<b.y<<" "<<res.x<<" "<<res.y<<endl;
if((sign(res.x-b.x)==0)&&(sign(res.y-b.y)==0))//如果交点就是第二高的点那么直接是0(不可能装水),极限情况就是交点和第三个点同样高
{
//cout<<"11"<<endl;
cout<<"0.00"<<endl;
continue;
}
k1=slope(res,a);
k2=slope(res,b);
//cout<<k1<<" "<<k2<<endl;
if(k1!=inf||k2!=inf)//如果斜率都存在
{
if((sign(k1)==-1)&&(sign(k2)==-1))//如果斜率小于0
{
if(sign(k1-k2)==-1)//只要最高点的那条直线的斜率比次高点的那条直线高
{
if(((sign(a.x-b.x)==0)||(sign(a.x-b.x)==-1))&&(sign(a.y-b.y)==1))//遮住了
{
//cout<<"1000"<<endl;
cout<<"0.00"<<endl;
continue;
}
}
}
if((sign(k1)==1)&&(sign(k2)==1))
{
if(sign(k1-k2)==1)//只要最高点的那条直线的斜率比次高点的那条直线高
{
if(((sign(a.x-b.x)==0)||(sign(a.x-b.x)==1))&&(sign(a.y-b.y)==1))//遮住了
{
// cout<<"2000"<<endl;
cout<<"0.00"<<endl;
continue;
}
}
}
}
c.y=b.y;
K=slope(res,a);
if(K==INF)
{
//cout<<"88"<<endl;
cout<<"0.00"<<endl;
continue;
}
if(K==inf)
{
c.x=res.x;
//cout<<"xxx"<<endl;
//cout<<res.x<<" "<<res.y<<" "<<c.x<<" "<<c.y<<" "<<b.x<<" "<<b.y<<endl;
printf("%.2lf\n",fabs(xmult(res,c,b))/2);
continue;
}
B=a.y-K*a.x;
if(sign(B)==0)
B=0;
//cout<<K<<" "<<B<<endl;
if(sign(c.y-B)==0)
c.x=0;
else
c.x=(c.y-B)/K;
if(sign(c.x)==0)
c.x=0;
//cout<<a.x<<" "<<b.x<<" "<<c.x<<endl;
//h=b.y-res.y;
// l=b.x-c.x;
//if(l<0)
// l=-l;
//area=0.5*l*h;
//cout<<"YYY"<<endl;
//cout<<res.x<<" "<<res.y<<" "<<c.x<<" "<<c.y<<" "<<b.x<<" "<<b.y<<endl;
printf("%.2lf\n",fabs(xmult(res,c,b))/2);
}
else
{
//cout<<"NO"<<endl;
cout<<"0.00"<<endl;
continue;
}
}
}
/*
9
样例一:
6259 2664 8292 9080 1244 2972 9097 9680
答案:6162.65
样例二:
0 1 1 0
1 0 2 1
答案:1.00
样例三:
0 1 2 1
1 0 1 2
答案:0.00
样例四:
0 0 10 10
0 0 9 8
答案:0.00
样例五:
0 0 10 10
0 0 8 9
答案:4.50
样例六:
0.9 3.1 4 0
0 3 2 2
答案:0.50
样例七:
0 0 0 2
0 0 -3 2
答案:3.00
样例八:
1 1 1 4
0 0 2 3
答案:0.75
样例九:
1 2 1 4
0 0 2 3
答案:0.00
*/
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator