传送门:Treasure Hunt

题意

有一个左下角为(0,0),右上角为(100,100)的正方形,给出n条线段,线段的起点和终点都在正方形上,给定一个宝藏的坐标,问从正方形外走到宝藏至少要经过多少条线段。每次只能走线段的中点,也就是每两个交点的中点。

题解

因为肯定是从正方形的边开始走,所以枚举每条边上的相邻两个点的中点,连接宝藏所在的点,看这条线段和几条线段有交点,并更新最小值。(为什么这么做是对的呢?因为我没找到反例(逃

存每条边上的点时记得排序 : ) ,忘记排序花式wa。

代码

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<math.h>
#define eps 1e-6
using namespace std;

struct point
{
    double x,y;
};

struct line
{
    point s,t;
}l[1000];

double a[10010];

double cross(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}

point operator - (point a,point b)
{
    return {a.x-b.x,a.y-b.y};
}

bool intersection(point a,point b,point c,point d)
{
    //快速排斥实验
    if(max(c.x,d.x)<min(a.x,b.x)||max(a.x,b.x)<min(c.x,d.x)||max(c.y,d.y)<min(a.y,b.y)||max(a.y,b.y)<min(c.y,d.y)){
        return false;
    }
    //跨立实验
    if(cross(a-d,c-d)*cross(b-d,c-d)>0||cross(d-b,a-b)*cross(c-b,a-b)>0){
        return  false;
    }
    return true;
}

int dcmp(double x)
{
    return fabs(x)<eps?0:x<0?-1:1;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lf%lf%lf%lf",&l[i].s.x,&l[i].s.y,&l[i].t.x,&l[i].t.y);
    }
    l[n++]={{0,0},{0,100}};
    l[n++]={{0,0},{100,0}};
    l[n++]={{100,100},{0,100}};
    l[n++]={{100,100},{100,0}};
    point q;
    scanf("%lf%lf",&q.x,&q.y);
    line p;
    int ans=0x3f3f3f3f;
    int k=0;
    for(int i=0;i<n;i++){
        if(dcmp(l[i].s.x)==0){
            a[k++]=l[i].s.y;
        }
        if(dcmp(l[i].t.x)==0){
            a[k++]=l[i].t.y;
        }
    }
    sort(a,a+k);
    for(int i=1;i<k;i++){
        p.s={0,(a[i]+a[i-1])/2.0};
        p.t=q;
        int cnt=0;
        for(int j=0;j<n;j++){
            if(intersection(p.s,p.t,l[j].s,l[j].t)) cnt++;
        }
        ans=min(ans,cnt);
    }
    k=0;
    for(int i=0;i<n;i++){
        if(dcmp(l[i].s.y)==0){
            a[k++]=l[i].s.x;
        }
        if(dcmp(l[i].t.y)==0){
            a[k++]=l[i].t.x;
        }
    }
    sort(a,a+k);
    for(int i=1;i<k;i++){
        p.s={(a[i]+a[i-1])/2.0,0.0};
        p.t=q;
        int cnt=0;
        for(int j=0;j<n;j++){
            if(intersection(p.s,p.t,l[j].s,l[j].t)) cnt++;
        }
        ans=min(ans,cnt);
    }
    k=0;
    for(int i=0;i<n;i++){
        if(dcmp(l[i].s.x-100)==0){
            a[k++]=l[i].s.y;
        }
        if(dcmp(l[i].t.x-100)==0){
            a[k++]=l[i].t.y;
        }
    }
    sort(a,a+k);
    for(int i=1;i<k;i++){
        p.s={100,(a[i]+a[i-1])/2.0};
        p.t=q;
        int cnt=0;
        for(int j=0;j<n;j++){
            if(intersection(p.s,p.t,l[j].s,l[j].t)) cnt++;
        }
        ans=min(ans,cnt);
    }

    k=0;
    for(int i=0;i<n;i++){
        if(dcmp(l[i].s.y-100)==0){
            a[k++]=l[i].s.x;
        }
        if(dcmp(l[i].t.y-100)==0){
            a[k++]=l[i].t.x;
        }
    }
    sort(a,a+k);
    for(int i=1;i<k;i++){
        p.s={(a[i]+a[i-1])/2.0,100};
        p.t=q;
        int cnt=0;
        for(int j=0;j<n;j++){
            if(intersection(p.s,p.t,l[j].s,l[j].t)) cnt++;
        }
        ans=min(ans,cnt);
    }
    if(q.x<0||q.x>100||q.y<0||q.y>100) ans=0;
    printf("Number of doors = %d\n",ans);
    return 0;
}