poj 1066

线段相交的问题;
关键是理解穿过最少的门,就是通过最少的线段,多个线段的交点,算作多个门,边界也需要门。所以n == 0的时候 == 1; 题意没看,有点晕;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define eps 0.0000000001  //看脸啊
struct point{
    double x,y;
};
struct seg{
    point s,e;
};
struct line {
    double A,B,C;
};
void cofficient(line &L,point a,point b) {
    L.A = b.y - a.y;
    L.B = a.x - b.x;
    L.C = -(L.A*a.x+L.B*a.y);
}
double cross(point a,point b,point c) { //向量ab * ac 叉乘
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y) ;
}
bool segcross(seg a,seg b) {
    bool flag = max(a.s.x,a.e.x) >= min(b.s.x,b.e.x) && max(a.s.y,a.e.y) >= min(b.s.y,b.e.y)
        && max(b.s.x,b.e.x) >= min(a.e.x,a.s.x) && max(b.s.y,b.e.y) >= min(a.s.y,a.e.y);
    if(!flag) return 0;
    double x = cross(a.s,b.e,b.s)*cross(b.e,a.e,b.s);
    double y = cross(b.s,a.e,a.s)*cross(a.e,b.e,a.s);
    return (fabs(x) < eps || x >= 0) && (fabs(y) < eps || y >= 0); 
}
void linecross(line L1,line L2,point &a) {
    a.x = -(L2.B*L1.C-L1.B*L2.C)/(L1.A*L2.B-L2.A*L1.B);
    a.y = (L2.A*L1.C-L1.A*L2.C)/(L1.A*L2.B-L2.A*L1.B);
}
double dis(point a,point b) {
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool pd(seg a,seg b) {
    double x1 = a.s.x-a.e.x;
    double y1 = a.s.y-a.e.y;
    double x2 = b.s.x-b.e.x;
    double y2 = b.s.y-b.e.y;
    double x = x1*y2 - x2*y1;
    if(fabs(x) < eps)
      return 1;
    return 0;
}

bool pequal(point a) {
    return fabs(a.x-100) < eps || fabs(a.y-100) < eps || fabs(a.x - 0) < eps || fabs(a.y-0) < eps;
}

point st;
seg data[100]={};
int n;
point dj[900]={};
int top;
int solve() {

    int mi = 100000;
    for(int i = 0; i < top; i++) {
        int ans = 0;
        seg c;c.e =dj[i];c.s = st;
        //printf("%lf %lf %lf %lf\n",c.e.x,c.e.y,st.x,st.y);
        for(int j = 0; j < n-4; j++) {
            if(segcross(c,data[j])) {
                ans++;
            }
        }
        mi = min(ans,mi);
    }
    if(mi == 100000)
      return 1;
    return mi;
}
int main() {
    scanf("%d",&n);
    for(int i = 0; i < n; i++) {
        scanf("%lf %lf %lf %lf",&data[i].s.x,&data[i].s.y,&data[i].e.x,&data[i].e.y);
        if(pequal(data[i].e))
          dj[top++] = data[i].e;
        if(pequal(data[i].s))
          dj[top++] = data[i].s;
    }
    data[n].s.x = 0,data[n].s.y = 0; data[n].e.x = 10,data[n++].e.y = 0;
    data[n].s.x = 0,data[n].s.y = 0; data[n].e.x = 0,data[n++].e.y = 10;
    data[n].s.x = 0,data[n].s.y = 10; data[n].e.x = 10,data[n++].e.y = 10;
    data[n].s.x = 10,data[n].s.y = 0; data[n].e.x = 10,data[n++].e.y = 10;
    scanf("%lf %lf",&st.x,&st.y);
    printf("Number of doors = %d\n",solve());
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值