pku 3304 Segments

http://acm.pku.edu.cn/JudgeOnline/problem?id=3304

假设存在 符合题意的一条直线l ,它经过所有线段。 那么, 必可以通过旋转,平移等操作,使得该直线至少经过两个

#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
#define FOR(i,s,e) for (int (i)=(s); (i) < (e);i++)
struct POINT
{
double x;
double y;
POINT(double a=0, double b=0) { x=a; y=b;} //constructor
};
struct LINESEG
{
POINT s;
POINT e;
LINESEG(POINT a, POINT b) { s=a; e=b;}
LINESEG() { }
};
struct LINE           // 直线的解析方程 a*x+b*y+c=0 为统一表示,约定 a >= 0
{
   double a;
   double b;
   double c;
   LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;}
};

const double INF = 1E20;
const double EP = 1E-9;
const int MAXV = 300;
const double PI = 3.14159265;
double multiply(POINT sp,POINT ep,POINT op)
{
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
bool intersect_l(LINESEG u,LINESEG v)
{
return multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=0;
}
bool cmp(POINT a,POINT b)
{
    return a.x < b.x || a.x == b.x && a.y < b.y;
}
int m;
int n;
POINT p[250];
LINESEG line[250];
int main()
{
// freopen("in.txt","r",stdin);
    int t ;
    scanf("%d",&t);
    bool sign_judge;
    while (t--)
    {
        m = 0;
        scanf("%d",&n);
        bool sign = true;
        double x = 0;
        FOR(i,0,n)
        {
            scanf("%lf%lf%lf%lf",&line[i].s.x,&line[i].s.y, &line[i].e.x, &line[i].e.y );
            p[m++] = line[i].s;
            p[m++] = line[i].e;
            if (i == 0) x = line[i].s.x;
            if (x != line[i].s.x || x != line[i].e.x)
            sign = false;
        }
        if (sign)
        printf("Yes!\n");
        else
        {
            sign_judge = true;
            sort(p,p+m,cmp);
         //   for (int i=0; i<m;i++)
        //    printf("%lf %lf\n",p[i].x,p[i].y);
            for (int i=0; i<m && sign_judge; i++)
            for (int j=i+1; j<m && sign_judge; j++)
            if (p[i].x != p[j].x)
            {
                bool sign_help = true;
                LINESEG light(p[i],p[j]);
                for (int k=0; k<n; k++)
                if (!intersect_l(line[k],light))
                {
            //        printf("i=%d j=%d k=%d\n",i,j,k);
                    sign_help = false;
                    break;
                }
                if (sign_help)
                {
                    sign_judge = false;
                }

            }
            if (!sign_judge)
            printf("Yes!\n");
            else
            printf("No!\n");
        }
    }
    return 0;
}

端点。 于是,可以通过枚举所有任意两个端点所生成的直线,判断其是否经过所有线段。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值