POJ 1410

 

http://poj.org/problem?id=1410

这道题搞了我好长时间啊,最后发现原来是原来的模板有问题,原来的模板中在判断线段相交的时候没有考虑线段共线且一个线段的一端点在另一条线段上这种情况,后来改了一

下,才过了。而且这道题要注意线段和矩形相交的定义,矩形包括四条边和中间的矩形区域,所以如果线段在矩形内部,也算是线段和矩形相交。

代码(别看代码长,全是模板!):

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

struct point
{
   double x,y;
}rect[4],line[2];

double xl,xr,yt,yb,xs,xe,ys,ye;

double min(double x,double y)
{
   if(x>y) return y;
   return x;
}
double max(double x,double y)
{
   if(x>y) return x;
   return y;
}

//判断double型的正数、负数和0,分别相应的返回1、-1和0
int dblcmp(double x)
{
   if(x==0) return 0;
   return (x>0)?1:-1;
}

//点积
double dot(double x1,double y1,double x2,double y2)
{
return x1*x2+y1*y2;
}

//求a点是不是在线段bc上,>0不在,=0与端点重合,<0在。
int point_on_line(point a,point b,point c)
{
return dblcmp(dot(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y));
}

//计算叉积
double det(double x1,double y1,double x2,double y2)
{return x1*y2-x2*y1;}

//计算a,b,c三点的叉积,判断a,b,c三点的位置关系
double cross(point a,point b,point c)
{return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);}

//判断线段是否相交,相交为true,不相交为false
int segcross(point a,point b,point c,point d)
{
   point p;
   int d1,d2,d3,d4;
   d1=dblcmp(cross(a,b,c));
   d2=dblcmp(cross(a,b,d));
   d3=dblcmp(cross(c,d,a));
   d4=dblcmp(cross(c,d,b));
   //规范相交
   if ((d1^d2)==-2 && (d3^d4)==-2) return 1;

   //不规范相交,就是两线段共线,并且一条线段的一段在另一条线段上
   if (d1==0 && point_on_line(c,a,b)<=0) {p=c;return 0;}
   if (d2==0 && point_on_line(d,a,b)<=0) {p=d;return 0;}
   if (d3==0 && point_on_line(a,c,d)<=0) {p=a;return 0;}
   if (d4==0 && point_on_line(b,c,d)<=0) return 0;
   //如果不相交
   return -1;
}

int main()
{
   double x1,y1,x2,y2;
   int n;
   scanf("%d",&n);
   for(int i=0;i<n;i++)
   {
      scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&xs,&ys,&xe,&ye,&x1,&y1,&x2,&y2);
      xl=min(x1,x2),xr=max(x1,x2);
      yt=max(y1,y2),yb=min(y1,y2);
      if(min(xs,xe)>=xl&&min(ys,ye)>=yb&&max(xs,xe)<=xr&&max(ys,ye)<=yt)
      {
         printf("T\n");
         continue;
      }
      line[0].x=xs,line[0].y=ys;
      line[1].x=xe,line[1].y=ye;
      rect[0].x=xl,rect[0].y=yt;
      rect[1].x=xl,rect[1].y=yb;
      rect[2].x=xr,rect[2].y=yb;
      rect[3].x=xr,rect[3].y=yt;
      bool flag=0;
      if(segcross(line[0],line[1],rect[0],rect[1])!=-1) flag=1;
      else if(segcross(line[0],line[1],rect[1],rect[2])!=-1) flag=1;
      else if(segcross(line[0],line[1],rect[2],rect[3])!=-1) flag=1;
      else if(segcross(line[0],line[1],rect[3],rect[0])!=-1) flag=1;
      if(flag) printf("T\n");
      else printf("F\n");
   }

   return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值